BZOJ - 4129: Haruna’s Breakfast
Haruna’s Breakfast
1 #include<cassert> 2 #include<cmath> 3 #include<cstdio> 4 #include<vector> 5 #include<iostream> 6 #include<algorithm> 7 #define pb push_back 8 using namespace std; 9 inline char nc() { 10 static char b[1<<14],*s=b,*t=b; 11 return s==t&&(t=(s=b)+fread(b,1,1<<14,stdin),s==t)?-1:*s++; 12 } 13 inline void read(int &x) { 14 char b = nc(); x = 0; 15 for (; !isdigit(b); b = nc()); 16 for (; isdigit(b); b = nc()) x = x * 10 + b - '0'; 17 } 18 const int N = 50010; 19 int n, m, a[N], ta[N]; 20 vector < int > g[N]; 21 inline void ae(int u, int v) { 22 g[u].pb(v); g[v].pb(u); 23 } 24 int sz[N], dep[N], fa[N], son[N], top[N]; 25 int I[N], O[N], D, f[N*2], bl[N*2], S; 26 int T, U[N], V[N], P[N]; 27 int cnt[N], tans, cn[N]; 28 void dfs1(int u, int f) { 29 sz[u] = 1; dep[u] = dep[f] + 1; fa[u] = f; 30 for (int i = 0, v; i < g[u].size(); ++i) if ((v = g[u][i]) != f) { 31 dfs1(v, u); sz[u] += sz[v]; if (sz[son[u]] < sz[v]) son[u] = v; 32 } 33 } 34 void dfs2(int u, int tp) { 35 I[u] = ++D; f[D] = u; 36 top[u] = tp; if (son[u]) dfs2(son[u], tp); 37 for (int i = 0, v; i < g[u].size(); ++i) 38 if (v = g[u][i], v != fa[u] && v != son[u]) dfs2(v, v); 39 O[u] = ++D; f[D] = u; 40 } 41 int findLca(int a, int b) { 42 for (; top[a] != top[b]; a = fa[top[a]]) 43 if (dep[top[a]] < dep[top[b]]) swap(a, b); 44 return dep[a] < dep[b] ? a : b; 45 } 46 struct Q { 47 int l, r, t, e, id; 48 inline void init(int u, int v, int i) { 49 id = i; if (I[u] > I[v]) swap(u, v); 50 e = findLca(u, v); t = T; 51 if (e == u) e = 0, l = I[u], r = I[v]; 52 else l = O[u], r = I[v]; 53 if (l > r) swap(l, r); 54 } 55 inline bool operator<(const Q &q) const { 56 if (bl[l] != bl[q.l]) return bl[l] < bl[q.l]; 57 if (r != q.r) return r < q.r; 58 return t < q.t; 59 } 60 } q[N]; 61 int qq, ans[N]; 62 inline void change(int x, int k) { 63 if (x > n) return; cnt[x] += k; 64 if (x < tans && !cnt[x]) tans = x; 65 assert(cnt[tans] >= 0); 66 while (cnt[tans]) ++tans; 67 } 68 inline void add(int t) { 69 if (cn[P[t]] == 1) change(U[t], -1), change(V[t], 1); 70 a[P[t]] = V[t]; 71 } 72 inline void del(int t) { 73 if (cn[P[t]] == 1) change(V[t], -1), change(U[t], 1); 74 a[P[t]] = U[t]; 75 } 76 inline void addn(int u) { 77 change(a[u], ++cn[u] == 1 ? 1 : -1); 78 } 79 inline void deln(int u) { 80 change(a[u], --cn[u] == 1 ? 1 : -1); 81 } 82 void solve() { 83 for (int l = 1, r = 0, t = 0, i = 1; i <= qq; ++i) { 84 while (t < q[i].t) add(++t); 85 while (t > q[i].t) del(t--); 86 while (r < q[i].r) addn(f[++r]); 87 while (r > q[i].r) deln(f[r--]); 88 while (l < q[i].l) deln(f[l++]); 89 while (l > q[i].l) addn(f[--l]); 90 if (q[i].e) addn(q[i].e); 91 ans[q[i].id] = tans; 92 if (q[i].e) deln(q[i].e); 93 } 94 } 95 int main() { 96 read(n); read(m); S = pow(n * 2, 0.666) + 1; 97 for (int i = 1; i <= n; ++i) read(a[i]), ta[i] = a[i]; 98 for (int i = 1; i <= n * 2; ++i) bl[i] = (i - 1) / S + 1; 99 for (int i = 1, u, v; i < n; ++i) 100 read(u), read(v), ae(u, v); 101 dfs1(1, 0); dfs2(1, 1); 102 for (int op, u, v, i = 0; i < m; ++i) { 103 read(op); read(u); read(v); 104 if (op) ++qq, q[qq].init(u, v, qq); 105 else {++T; P[T] = u; U[T] = ta[u]; V[T] = v; ta[u] = v;} 106 } sort(q + 1, q + 1 + qq); solve(); 107 for (int i = 1; i <= qq; ++i) printf("%d\n", ans[i]); 108 return 0; 109 }
题意:求树链上的mex,可修改。
题解:mex用分块维护,在树上莫队转移即可。