zoukankan      html  css  js  c++  java
  • 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('
    ');}
    }
    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;
    }
    
  • 相关阅读:
    Go语言基础之包
    Go语言基础之结构体
    Go语言基础之函数
    Go语言基础之map
    Go语言基础之指针
    Go语言基础之切片
    Go语言基础之数组
    02-Spring配置文件加载
    01-Spring概述(总览)
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12218492.html
Copyright © 2011-2022 走看看