제출 #284322

#제출 시각아이디문제언어결과실행 시간메모리
284322rama_pangCats or Dogs (JOI18_catdog)C++14
100 / 100
247 ms20088 KiB
#include "catdog.h" #include <bits/stdc++.h> using namespace std; const int INF = 1e7; const int MAXN = 1e5 + 5; class Node { public: int par, ch[2], state; array<int, 2> sum; // sum of dp of light children array<array<int, 2>, 2> dp; // merged values on chain (dp[i][j] = start from color i, ending at color j) Node() { par = ch[0] = ch[1] = 0; state = 2; sum = {0, 0}; dp[0] = {0, INF}; dp[1] = {INF, 0}; } void ChangeState(int t) { state = t; } int Answer() { return min({dp[0][0], dp[0][1], dp[1][0], dp[1][1]}); } }; int root; Node tree[MAXN]; int sub[MAXN]; int heavy[MAXN]; vector<int> adj[MAXN]; bool IsChainRoot(int u) { return tree[tree[u].par].ch[0] != u && tree[tree[u].par].ch[1] != u; } void Reupdate(int u) { // array<int, 2>{1, 0}}); tree[u].dp[0] = {tree[u].sum[0], INF}; tree[u].dp[1] = {INF, tree[u].sum[1]}; if (tree[u].state == 0) { tree[u].dp[0][0] = INF; } else if (tree[u].state == 1) { tree[u].dp[1][1] = INF; } if (tree[u].ch[1]) { array<array<int, 2>, 2> res; res[0] = res[1] = {INF, INF}; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { res[i][j] = min(res[i][j], (k != l) + tree[u].dp[i][k] + tree[tree[u].ch[1]].dp[l][j]); } } } } tree[u].dp = res; } if (tree[u].ch[0]) { array<array<int, 2>, 2> res; res[0] = res[1] = {INF, INF}; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { res[i][j] = min(res[i][j], (k != l) + tree[tree[u].ch[0]].dp[i][k] + tree[u].dp[l][j]); } } } } tree[u].dp = res; } } void UpdateSum(int p, int u, int sgn) { tree[p].sum[0] += sgn * min({tree[u].dp[0][0], tree[u].dp[0][1], tree[u].dp[1][0] + 1, tree[u].dp[1][1] + 1}); tree[p].sum[1] += sgn * min({tree[u].dp[1][0], tree[u].dp[1][1], tree[u].dp[0][0] + 1, tree[u].dp[0][1] + 1}); } int Update(int u, int type) { tree[u].ChangeState(type); for (; u; u = tree[u].par) { if (tree[u].par && IsChainRoot(u)) { UpdateSum(tree[u].par, u, -1); Reupdate(u); UpdateSum(tree[u].par, u, +1); } else { Reupdate(u); } } return tree[root].Answer(); } void DfsInit(int u, int p) { if (p) { adj[u].erase(find(begin(adj[u]), end(adj[u]), p)); } sub[u] = 1; for (auto &v : adj[u]) { DfsInit(v, u); sub[u] += sub[v]; if (!heavy[u] || sub[heavy[u]] < sub[v]) { heavy[u] = v; } } } int Build(int l, int r, const vector<int> &chain) { if (l > r) return 0; int all = 0, cur = 0, mid; for (int i = l; i <= r; i++) all += sub[chain[i]]; for (mid = l; mid <= r; mid++) { cur += sub[chain[mid]]; if (cur * 2 > all) { break; } } int id = chain[mid]; tree[id].ch[0] = Build(l, mid - 1, chain); tree[id].ch[1] = Build(mid + 1, r, chain); if (tree[id].ch[0]) tree[tree[id].ch[0]].par = id; if (tree[id].ch[1]) tree[tree[id].ch[1]].par = id; Reupdate(id); return id; } int Construct(int u) { for (int i = u; i; i = heavy[i]) { for (auto v : adj[i]) { if (v != heavy[i]) { int r = Construct(v); tree[r].par = i; UpdateSum(i, r, +1); } } } static vector<int> chain; chain.clear(); for (int i = u; i; i = heavy[i]) { chain.emplace_back(i); } for (int i = 0; i + 1 < (int) chain.size(); i++) { sub[chain[i]] -= sub[chain[i + 1]]; } return Build(0, int(chain.size()) - 1, chain); } void initialize(int N, vector<int> A, vector<int> B) { for (int i = 0; i + 1 < N; i++) { adj[A[i]].emplace_back(B[i]); adj[B[i]].emplace_back(A[i]); } DfsInit(1, 0); root = Construct(1); } int cat(int v) { return Update(v, 0); } int dog(int v) { return Update(v, 1); } int neighbor(int v) { return Update(v, 2); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...