模板。树上莫队的分块就是按dfn分,然后区间之间转移时注意一下就好。有个图方便理解http://blog.csdn.net/thy_asdf/article/details/47377709;
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; const int maxn=50010; int ccc[maxn],col[maxn],n,m,last[maxn],pre[maxn*2],other[maxn*2],d[maxn],bel[maxn],f[maxn][25]; int res,bo,ind,dfn[maxn],ans[maxn*2],t,cnt,sta[maxn],top,vis[maxn],tong[maxn],ttt[maxn]; struct que{ int u,v,id; bool operator<(const que&tmp)const{ if(bel[u]==bel[tmp.u])return dfn[v]<dfn[tmp.v]; return bel[u]<bel[tmp.u]; } }q[maxn*2]; void add(int x,int y){++t;pre[t]=last[x];last[x]=t;other[t]=y;} int dfs(int x){ int siz=0; dfn[x]=++ind; for(int i=last[x];i;i=pre[i]){ int v=other[i]; if(v==f[x][0])continue; d[v]=d[x]+1;f[v][0]=x; siz+=dfs(v); if(siz>=bo){ ++cnt; for(int j=1;j<=siz;++j) bel[sta[top--]]=cnt; siz=0; } } sta[++top]=x; return siz+1; } void change(int x){ if(!vis[x]){vis[x]=1;tong[col[x]]++;if(tong[col[x]]==1)res++;} else{vis[x]=0;tong[col[x]]--;if(tong[col[x]]==0)res--;} } void solve(int u,int v){ while(u!=v){ if(d[u]>d[v])change(u),u=f[u][0]; else change(v),v=f[v][0]; } } int lca(int x,int y){ if(d[x]<d[y])swap(x,y); for(int i=20;i>=0;--i) if(d[f[x][i]]>=d[y])x=f[x][i]; if(x==y)return x; for(int i=20;i>=0;--i) if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } int main(){ cin>>n>>m; int x,y;bo=sqrt(n+0.5); for(int i=1;i<=n;++i){ scanf("%d",&ccc[i]); ttt[i]=ccc[i]; } sort(ttt+1,ttt+n+1); int len=unique(ttt+1,ttt+n+1)-ttt-1; for(int i=1;i<=n;++i){ col[i]=lower_bound(ttt+1,ttt+len+1,ccc[i])-ttt; } for(int i=1;i<n;++i){ scanf("%d%d",&x,&y); add(x,y);add(y,x); } d[1]=1;dfs(1); ++cnt; while(top)bel[sta[top--]]=cnt; for(int j=1;j<=20;++j) for(int i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1]; for(int i=1;i<=m;++i){ q[i].id=i; scanf("%d%d",&q[i].u,&q[i].v); if(dfn[q[i].u]>dfn[q[i].v])swap(q[i].u,q[i].v); } sort(q+1,q+m+1); int op=lca(q[1].u,q[1].v); solve(q[1].u,q[1].v); change(op);ans[q[1].id]=res;change(op); for(int i=2;i<=m;++i){ solve(q[i-1].u,q[i].u);solve(q[i-1].v,q[i].v); op=lca(q[i].u,q[i].v); change(op);ans[q[i].id]=res;change(op); } for(int i=1;i<=m;++i){ printf("%d\n",ans[i]); } //system("pause"); return 0; }