题解:
树上+可修改莫队
莫队的每一块
可以用一个栈
每一次dfs个数>sqrt(n)(自己选的)的时候就可以跳出了
然后不要忘记分出来最后一块
代码:
#include<bits/stdc++.h> using namespace std; const int N=400005; int k=1,fi[N],unit,Be[N],m,st[N],top,fa[N][18],deep[N],n,Q; int a[N],t[N],op,x,y,p,tim,u=1,v=1,T,ans[N],vis[N],ne[N],zz[N]; struct Change { int u,New,Old; }cq[N]; struct Query { int u,v,tim,id; int operator <(const Query &a) const { if (Be[u]!=Be[a.u])return Be[u]<Be[a.u]; if (Be[v]!=Be[a.v])return Be[v]<Be[a.v]; return tim<a.tim; } }q[N]; struct Datalook { struct _bol{int l,r;}b[350]; int n,Be[N],m,unit,num[N],sum[350]; void init() { unit=sqrt(n); m=(n-1)/unit+1; for (int i=1;i<=n;i++)Be[i]=(i-1)/unit+1; for (int i=1;i<=m;i++)b[i].l=(i-1)*unit+1,b[i].r=i*unit; b[m].r=n; } void Add(int v) { if (v<=n)sum[Be[v]]+=(++num[v])==1; } void Del(int v) { if (v<=n)sum[Be[v]]-=(--num[v])==0; } int mex() { for (int i=1;i<=m;i++) if (sum[i]!=b[i].r-b[i].l+1) for (int j=b[i].l;j<=b[i].r;j++) if (!num[j])return j; return -1; } }Data; void jb(int u,int v) { ne[k]=fi[u]; zz[k]=v; fi[u]=k++; } void dfs(int u) { for (int i=1;i<=19;i++) if ((1<<i)>deep[u])break; else fa[u][i]=fa[fa[u][i-1]][i-1]; int bottom=top; for (int i=fi[u];i;i=ne[i]) { int v=zz[i]; if (v!=fa[u][0]) { fa[v][0]=u; deep[v]=deep[u]+1; dfs(v); if (top-bottom>=unit) { m++; while (top!=bottom)Be[st[top--]]=m; } } } st[++top]=u; } int Lca(int x,int y) { if (deep[x]<deep[y])swap(x,y); int Dis=deep[x]-deep[y]; for (int i=0;i<=16;i++) if ((1<<i)&Dis)x=fa[x][i]; if (x==y)return x; for (int i=16;i>=0;i--) if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; return x==y?x:fa[x][0]; } void revise(int u,int d) { if (vis[u]) { Data.Del(a[u]); Data.Add(d); } a[u]=d; } void run(int u) { if (vis[u]) { Data.Del(a[u]); vis[u]=0; } else { Data.Add(a[u]); vis[u]=1; } } void move(int x,int y) { if (deep[x]<deep[y])swap(x,y); while (deep[x]>deep[y])run(x),x=fa[x][0]; while (x!=y)run(x),run(y),x=fa[x][0],y=fa[y][0]; } int main() { scanf("%d%d",&n,&Q); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); t[i]=++a[i]; } for (int i=2;i<=n;i++) { scanf("%d%d",&x,&y); jb(x,y);jb(y,x); } dfs(1); while (top)Be[st[top--]]=m; for (int i=1;i<=Q;i++) { scanf("%d%d%d",&op,&x,&y); if (op)q[++p]=(Query){x,y,tim,p}; if (!op)cq[++tim]=(Change){x,y+1,t[x]},t[x]=y+1; } Data.n=n+1; Data.init(); sort(q+1,q+1+p); for (int i=1;i<=p;i++) { while (T<q[i].tim)T++,revise(cq[T].u,cq[T].New); while (T>q[i].tim)revise(cq[T].u,cq[T].Old),T--; if(u!=q[i].u)move(u,q[i].u),u=q[i].u; if(v!=q[i].v)move(v,q[i].v),v=q[i].v; int anc=Lca(u,v); run(anc); ans[q[i].id]=Data.mex()-1; run(anc); } for (int i=1;i<=p;i++)printf("%d\n",ans[i]); }