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 }
View Code

题意:求树链上的mex,可修改。

题解:mex用分块维护,在树上莫队转移即可。

posted @ 2017-12-28 16:11  p0ny  阅读(112)  评论(0编辑  收藏  举报