Submission #1270193

#TimeUsernameProblemLanguageResultExecution timeMemory
1270193MisterReaperCats or Dogs (JOI18_catdog)C++20
0 / 100
0 ms328 KiB
// 15:59
#include "bits/stdc++.h"
#include "catdog.h"

#ifdef DEBUG 
    #include "/home/ahmetalp/Desktop/Workplace/debug.h"
#else
    #define debug(...) void(23)
#endif

using i64 = long long;

constexpr i64 inf = i64(1E9);

using M = std::array<std::array<i64, 2>, 2>;

M operator+ (M lhs, M rhs) {
    M res {};
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 2; ++j) {
            res[i][j] = std::min({lhs[i][0] + rhs[0][j], 
                                  lhs[i][0] + rhs[1][j] + 1, 
                                  lhs[i][1] + rhs[0][j] + 1, 
                                  lhs[i][1] + rhs[1][j]});
        }
    }
    return res;
}

#define def int mid = (l + r) >> 1, lv = v + 1, rv = v + ((mid - l + 1) << 1)

struct segtree {
    int n;
    std::vector<M> tree;
    segtree() {}
    segtree(int n_) : n(n_), tree(n << 1) {
        auto dfs = [&](auto&& self, int v, int l, int r) -> void {
            if (l == r) {
                tree[v] = {0, inf, inf, 0};
                return;
            }
            def;
            self(self, lv, l, mid);
            self(self, rv, mid + 1, r);
            tree[v] = tree[lv] + tree[rv];
        };
        dfs(dfs, 0, 0, n - 1);
    }
    void init(int n_) {
        n = n_;
        tree.assign(n << 1, {});
        auto dfs = [&](auto&& self, int v, int l, int r) -> void {
            if (l == r) {
                tree[v] = {0, inf, inf, 0};
                return;
            }
            def;
            self(self, lv, l, mid);
            self(self, rv, mid + 1, r);
            tree[v] = tree[lv] + tree[rv];
        };
        dfs(dfs, 0, 0, n - 1);
    }
    void modify(int v, int l, int r, int p, int k, i64 x) {
        if (l == r) {
            tree[v][k >> 1][k & 1] += x;
            return;
        }
        def;
        if (p <= mid) {
            modify(lv, l, mid, p, k, x);
        } else {
            modify(rv, mid + 1, r, p, k, x);
        }
        tree[v] = tree[lv] + tree[rv];
    }
    void modify(int p, int k, i64 x) {
        modify(0, 0, n - 1, p, k, x);
    }
    M get(int v, int l, int r, int ql, int qr) {
        if (ql == l && r == qr) {
            return tree[v];
        }
        def;
        if (qr <= mid) {
            return get(lv, l, mid, ql, qr);
        } else if (mid + 1 <= ql) {
            return get(rv, mid + 1, r, ql, qr);
        } else {
            return get(lv, l, mid, ql, mid)
                 + get(rv, mid + 1, r, mid + 1, qr);
        }
    }
    M get(int l, int r) {
        return get(0, 0, n - 1, l, r);
    }
} seg;

int tim;
std::vector<int> tp;
std::vector<int> siz, par, top, tin, len;
std::vector<std::vector<int>> adj;

void dfs1(int v) {
    for (auto& u : adj[v]) {
        adj[u].erase(std::find(adj[u].begin(), adj[u].end(), v));
        par[u] = v;
        dfs1(u);
        siz[v] += siz[u];
        if (siz[u] > siz[adj[v][0]]) {
            std::swap(adj[v][0], u);
        }
    }
}

void dfs2(int v) {
    len[top[v]]++;
    tin[v] = tim++;
    for (auto& u : adj[v]) {
        top[u] = (u == adj[v][0] ? top[v] : u);
        dfs2(u);
    }
}

void initialize(int N, std::vector<int> A, std::vector<int> B) {
    tp.assign(N, 0);
    siz.assign(N, 1);
    par.assign(N, 0);
    top.assign(N, {});
    tin.assign(N, 0);
    len.assign(N, 0);
    adj.assign(N, {});
    seg.init(N);
    for (int i = 0; i < N - 1; ++i) {
        --A[i], --B[i];
        adj[A[i]].emplace_back(B[i]);
        adj[B[i]].emplace_back(A[i]);
    }

    debug(0);
    dfs1(0);
    debug(1);
    dfs2(0);
    debug(2);
}

void add(int v, int t) {
    debug("add", v, t);
    int u = v;
    while (top[u] != 0) {
        if (u == top[u]) {
            M x = seg.get(tin[u], tin[u] + len[u] - 1);
            debug(x);
            seg.modify(tin[par[u]], 0, t * std::min({x[0][0], x[0][1], x[1][0] + 1, x[1][1] + 1}));
            seg.modify(tin[par[u]], 3, t * std::min({x[0][0] + 1, x[0][1] + 1, x[1][0], x[1][1]}));
            u = par[u];
        } else {
            u = top[u];
        }
    }
}

int answer() {
    M res = seg.get(0, len[0] - 1);
    debug("answer", res);
    i64 ans = inf;
    for (int i = 0; i < 4; ++i) {
        ans = std::min(ans, res[i >> 1][i & 1]);
    }
    return ans;
}

int cat(int v) {
    debug("cat", v);
    --v;
    add(v, -1);
    tp[v] = 1;
    seg.modify(tin[v], 3, inf);
    add(v, +1);
    return answer();
}

int dog(int v) {
    debug("dog", v);
    --v;
    add(v, -1);
    tp[v] = 2;
    seg.modify(tin[v], 0, inf);
    add(v, +1);
    return answer();
}

int neighbor(int v) {
    debug("neighbor", v);
    --v;
    add(v, -1);
    if (tp[v] == 1) {
        seg.modify(tin[v], 3, -inf);
    } else if (tp[v] == 2) {
        seg.modify(tin[v], 0, -inf);
    } else {
        assert(false);
    }
    tp[v] = 0;
    add(v, +1);
    return answer();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...