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;
}
posted @ 2020-01-20 16:35  Shiina_Mashiro  阅读(132)  评论(0编辑  收藏  举报