This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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;
int sum[2]; // sum of dp of light children
int dp[2][2]; // 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] = sum[1] = 0;
dp[0][0] = 0; dp[0][1] = INF;
dp[1][0] = INF; dp[1][1] = 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][0] = tree[u].sum[0]; tree[u].dp[0][1] = INF;
tree[u].dp[1][0] = INF; tree[u].dp[1][1] = 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;
}
static int res[2][2];
if (tree[u].ch[1]) {
res[0][0] = res[0][1] = res[1][0] = res[1][1] = INF;
int oth = tree[u].ch[1];
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[oth].dp[l][j]);
}
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
tree[u].dp[i][j] = res[i][j];
}
}
}
if (tree[u].ch[0]) {
res[0][0] = res[0][1] = res[1][0] = res[1][1] = INF;
int oth = tree[u].ch[0];
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[oth].dp[i][k] + tree[u].dp[l][j]);
}
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
tree[u].dp[i][j] = res[i][j];
}
}
}
}
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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |