Ynoi2016 这是我自己的发明
Link
首先可以发现这个换根是个假的,我们可以通过dfs序把这棵树拍成序列,那么不论怎么换根一个点的子树最多是两个区间,这个随便讨论一下就行了。
然后就是Link了,直接做就好了。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
void Put(char x){*oS++=x;if(oS==oT)Flush();}
int read(){int x=0,f=1;char ch=Get();while((ch>57||ch<48)&&ch^'-')ch=Get();if(ch=='-')ch=Get(),f=-1;while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return f*x;}
void write(LL x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');}
}
using namespace IO;
#define N 100007
int n,tot,cnt,Time,bel[N],a[N],t[N],b[N],c[N],head[N],ver[N<<1],Next[N<<1],fa[N],size[N],son[N],top[N],rate[N],pos[N];
LL ans[N*5],Ans;
struct query{int l,r,id,opt;}q[N*80];
int operator<(query a,query b){return bel[a.l]^bel[b.l]? bel[a.l]<bel[b.l]:(bel[a.l]&1? a.r<b.r:a.r>b.r);}
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
void dfs(int u,int Fa)
{
fa[u]=Fa,size[u]=1;
for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^Fa) dfs(v,u),size[u]+=size[v],son[u]=size[v]>size[son[u]]? v:son[u];
}
void Dfs(int u,int Top)
{
top[u]=Top,rate[u]=++Time,pos[Time]=a[u];
if(son[u]) Dfs(son[u],Top);
for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^fa[u]&&v^son[u]) Dfs(v,v);
}
int Son(int u,int v)
{
while(top[u]^top[v]){u=top[u];if(fa[u]==v)return u;u=fa[u];}
return son[v];
}
void Add(int l,int r,int L,int R,int id)
{
if(l<1||L<1||r>n||R>n||l>r||L>R) return ;
q[++cnt]=query{r,R,id,1};
if(l>1) q[++cnt]=query{l-1,R,id,-1};
if(L>1) q[++cnt]=query{L-1,r,id,-1};
if(l>1&&L>1) q[++cnt]=query{l-1,L-1,id,1};
}
void modifyb(int p,int opt){Ans+=1ll*opt*c[pos[p]],b[pos[p]]+=opt;}
void modifyc(int p,int opt){Ans+=1ll*opt*b[pos[p]],c[pos[p]]+=opt;}
int main()
{
n=read();int i,u,v,w,num=0,L,R,root=1,len,Size=sqrt(n),m=read();
for(i=1;i<=n;++i) t[i]=a[i]=read(),bel[i]=(i-1)/Size;
sort(t+1,t+n+1),len=unique(t+1,t+n+1)-(t+1);
for(i=1;i<=n;++i) a[i]=lower_bound(t+1,t+len+1,a[i])-t;
for(i=1;i<n;++i) u=read(),v=read(),add(u,v),add(v,u);
dfs(1,0),Dfs(1,1);
for(i=1;i<=m;++i)
{
if(read()==1) root=read();
else
{
++num,u=read(),v=read();
if(u==root)
{
if(v==root) Add(1,n,1,n,num);
else if(rate[v]<rate[root]&&rate[root]+size[root]<=rate[v]+size[v]) w=Son(root,v),Add(1,n,1,rate[w]-1,num),Add(1,n,rate[w]+size[w],n,num);
else Add(1,n,rate[v],rate[v]+size[v]-1,num);
}
else if(rate[u]<rate[root]&&rate[root]+size[root]<=rate[u]+size[u])
{
w=Son(root,u),L=rate[w],R=rate[w]+size[w]-1;
if(v==root) Add(1,L-1,1,n,num),Add(R+1,n,1,n,num);
else if(rate[v]<rate[root]&&rate[root]+size[root]<=rate[v]+size[v]) w=Son(root,v),Add(1,L-1,1,rate[w]-1,num),Add(1,L-1,rate[w]+size[w],n,num),Add(R+1,n,1,rate[w]-1,num),Add(R+1,n,rate[w]+size[w],n,num);
else Add(1,L-1,rate[v],rate[v]+size[v]-1,num),Add(R+1,n,rate[v],rate[v]+size[v]-1,num);
}
else
{
if(v==root) Add(rate[u],rate[u]+size[u]-1,1,n,num);
else if(rate[v]<rate[root]&&rate[root]+size[root]<=rate[v]+size[v]) w=Son(root,v),Add(rate[u],rate[u]+size[u]-1,1,rate[w]-1,num),Add(rate[u],rate[u]+size[u]-1,rate[w]+size[w],n,num);
else Add(rate[u],rate[u]+size[u]-1,rate[v],rate[v]+size[v]-1,num);
}
}
}
sort(q+1,q+cnt+1);
for(i=1,L=R=0;i<=cnt;++i)
{
while(L<q[i].l) ++L,modifyb(L,1);
while(L>q[i].l) modifyb(L,-1),--L;
while(R<q[i].r) ++R,modifyc(R,1);
while(R>q[i].r) modifyc(R,-1),--R;
ans[q[i].id]+=1ll*q[i].opt*Ans;
}
for(i=1;i<=num;++i) write(ans[i]);
return Flush(),0;
}