BZOJ4129: Haruna’s Breakfast
http://www.lydsy.com/JudgeOnline/problem.php?id=4129
树上带修改求mex,树上带修改莫队即可。
#include<bits/stdc++.h> using namespace std; const int maxn=50015,maxe=100015,maxm=50015,maxb=255,maxk=20; int n,m,ask,tim,a[maxn]; struct Tmodify{int x,v;}M[maxm]; struct Tquery{int idx,u,v,t;}Q[maxm]; int tot,now[maxn],pre[maxe],son[maxe]; void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;} void init(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int u,v,i=1;i<=n-1;++i){ scanf("%d%d",&u,&v); connect(u,v);connect(v,u); } for (int t,u,v,i=1;i<=m;++i){ scanf("%d%d%d",&t,&u,&v); switch (t){ case 0:M[++tim]=(Tmodify){u,v};break; case 1:Q[++ask]=(Tquery){ask,u,v,tim};break; } } } int dep[maxn],anc[maxn][maxk]; void get_anc(int u,int f){ anc[u][0]=f;dep[u]=dep[f]+1; for (int k=1;k<maxk;++k) anc[u][k]=anc[anc[u][k-1]][k-1]; for (int p=now[u];p;p=pre[p]) if (son[p]!=f) get_anc(son[p],u); } int siz1,top,cnt,stk[maxn],bel[maxn]; void get_block(int u,int f){ for (int bot=top,p=now[u];p;p=pre[p]){ if (son[p]==f) continue;get_block(son[p],u); if (top-bot>=siz1) for (++cnt;top!=bot;bel[stk[top--]]=cnt); } stk[++top]=u; } bool cmp(Tquery a,Tquery b){ if (bel[a.u]!=bel[b.u]) return bel[a.u]<bel[b.u]; else if (bel[a.v]!=bel[b.v]) return bel[a.v]<bel[b.v]; else return a.t<b.t; } void prepare(){ siz1=pow(n,0.67); get_anc(1,0);get_block(1,0); while (top) bel[stk[top--]]=cnt; for (int i=1;i<=ask;++i) if (bel[Q[i].u]>bel[Q[i].v]) swap(Q[i].u,Q[i].v); sort(Q+1,Q+ask+1,cmp); } bool exist[maxn]; int num,siz2,ans[maxm],bl[maxb],br[maxb],have[maxb],idx[maxn],sum[maxn]; void xor_node(int u){ if (exist[u]){if (a[u]<=n) if (!--sum[a[u]]) --have[idx[a[u]]];} else if (a[u]<=n) if (!sum[a[u]]++) ++have[idx[a[u]]]; exist[u]^=1; } void xor_path(int u,int v){ if (dep[u]<dep[v]) swap(u,v); while (dep[u]!=dep[v]){xor_node(u);u=anc[u][0];} while (u!=v){xor_node(u);xor_node(v);u=anc[u][0];v=anc[v][0];} } void modify(int t){ int x=M[t].x,v=M[t].v; if (exist[x]){ if (a[x]<=n) if (!--sum[a[x]]) --have[idx[a[x]]]; if (v<=n) if (!sum[v]++) ++have[idx[v]]; } swap(M[t].v,a[x]); } void move_time(int ever,int now){ for (int i=ever+1;i<=now;++i) modify(i); for (int i=ever;i>=now+1;--i) modify(i); } int lca(int u,int v){ if (dep[u]<dep[v]) swap(u,v); for (int h=dep[u]-dep[v],i=0;h;h>>=1,++i) if (h&1) u=anc[u][i]; for (int k=maxk-1;k>=0;--k) if (anc[u][k]!=anc[v][k]){u=anc[u][k];v=anc[v][k];} return u==v?u:anc[u][0]; } int get_ans(){ int pos,res; for (pos=0;have[pos]==siz2;++pos); for (res=bl[pos];sum[res];++res); return res; } void solve(int k){ xor_path(Q[k-1].u,Q[k].u); xor_path(Q[k-1].v,Q[k].v); move_time(Q[k-1].t,Q[k].t); int x=lca(Q[k].u,Q[k].v); xor_node(x);ans[Q[k].idx]=get_ans();xor_node(x); } void work(){ prepare();siz2=sqrt(n); for (int j,i=0;i<=n;i=j,++num){ for (j=i;j-i+1<=siz2&&j<=n;++j) idx[j]=num; bl[num]=i;br[num]=j-1; } for (int i=1;i<=ask;++i) solve(i); for (int i=1;i<=ask;++i) printf("%d\n",ans[i]); } int main(){ init(); work(); return 0; }