제출 #401580

#제출 시각아이디문제언어결과실행 시간메모리
401580timmyfengCats or Dogs (JOI18_catdog)C++17
100 / 100
347 ms38340 KiB
#include <bits/stdc++.h>
using namespace std;

const int N = 100001;

struct segtree {
    segtree *left, *right;
    array<long long, 4> mini;

    void pull() {
        mini = {N, N, N, N};
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                int k = i / 2 * 2 + j % 2;
                mini[k] = min(mini[k], left->mini[i] + right->mini[j] + (i % 2 != j / 2));
            }
        }
    }

    segtree(int l, int r) {
        if (l == r) {
            mini = {0, N, N, 0};
        } else {
            int m = (l + r) / 2;
            left = new segtree(l, m);
            right = new segtree(m + 1, r);
            pull();
        }
    }

    void update(int a, long long x, long long y, int l, int r) {
        if (l == r) {
            mini[0] += x;
            mini[3] += y;
        } else {
            int m = (l + r) / 2;
            if (a <= m) {
                left->update(a, x, y, l, m);
            } else {
                right->update(a, x, y, m + 1, r);
            }
            pull();
        }
    }
};

int par[N], sub[N], in[N], head[N], tail[N];
segtree *path[N];

vector<int> adj[N];
int type[N];

void dfs_sub(int u) {
    sub[u] = 1;
    for (auto &c : adj[u]) {
        adj[c].erase(find(adj[c].begin(), adj[c].end(), u));
        par[c] = u;

        dfs_sub(c);
        sub[u] += sub[c];
        if (sub[c] > sub[adj[u][0]]) {
            swap(adj[u][0], c);
        }
    }
}

void dfs_hld(int u) {
    sub[u] = 0;
    for (auto c : adj[u]) {
        if (c == adj[u][0]) {
            head[c] = head[u];
            in[c] = in[u] + 1;
        } else {
            head[c] = c;
        }
        dfs_hld(c);
    }
    ++sub[head[u]];
}

array<long long, 2> get(array<long long, 4> &a) {
    long long x = min(a[0], a[1]), y = min(a[2], a[3]);
    return {min(x, y + 1), min(x + 1, y)};
}

void dfs_build(int u) {
    if (head[u] == u) {
        path[u] = new segtree(0, sub[u] - 1);
    }

    for (auto c : adj[u]) {
        dfs_build(c);
    }

    if (head[u] == u && u > 1) {
        array<long long, 2> mini = get(path[u]->mini);
        int p = par[u], v = head[p];
        path[v]->update(in[p], mini[0], mini[1], 0, sub[v] - 1);
    }
}

void update(int u, long long x, long long y) {
    while (u > 0) {
        int v = head[u];

        array<long long, 2> prv = get(path[v]->mini);
        path[v]->update(in[u], x, y, 0, sub[v] - 1);
        array<long long, 2> cur = get(path[v]->mini);

        u = par[v];
        x = cur[0] - prv[0];
        y = cur[1] - prv[1];
    }
}

long long query() {
    array<long long, 4> mini = path[1]->mini;
    return *min_element(mini.begin(), mini.end());
}

void initialize(int n, vector<int> a, vector<int> b) {
    for (int i = 0; i < n - 1; ++i) {
        adj[a[i]].push_back(b[i]);
        adj[b[i]].push_back(a[i]);
    }

    fill(type, type + n + 1, -1);

    head[1] = 1;

    dfs_sub(1);
    dfs_hld(1);
    dfs_build(1);
}

int cat(int u) {
    update(u, 0, N);
    type[u] = 0;
    return query();
}

int dog(int u) {
    update(u, N, 0);
    type[u] = 1;
    return query();
}

int neighbor(int u) {
    if (type[u] == 0) {
        update(u, 0, -N);
    } else {
        update(u, -N, 0);
    }
    type[u] = -1;
    return query();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...