zoukankan      html  css  js  c++  java
  • BZOJ 3091: 城市旅行 LCT

    维护 $sum_{}v[i] imes dep[i]$ 与 $sum_{} v[i] imes dep[i]^2$

    其中 $dep[i]$ 表示 $i$ 点在该点所在 $LCT$ 的 $splay$ 中的中序遍历序.

    然后正着维护一个,反着维护一个就行了.              

    #include <cstdio>  
    #include <cstring> 
    #include <string>
    #include <map>
    #include <algorithm>   
    #define N 50005  
    #define ll long long   
    #define siz size       
    #define ts tag
    #define lson s[x].ch[0] 
    #define rson s[x].ch[1]    
    #define get(x) (s[s[x].f].ch[1]==x) 
    #define Isr(x) (!(s[s[x].f].ch[0]==x||s[s[x].f].ch[1]==x))        
    using namespace std;   
    
    ll sqr(ll x) { return x*x;  }   
    ll calc1(ll x) { return x*(x+1ll)/2; }   
    ll calc2(ll x) { return x*(x+1ll)*(2ll*x+1ll)/6; }   
    ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;  }
    
    namespace IO {      
    
        void setIO(string s) 
        {
            string in=s+".in"; 
            string out=s+".out"; 
            freopen(in.c_str(),"r",stdin); 
            freopen(out.c_str(),"w",stdout); 
        }     
    
    };          
     
    int sta[N]; 
    map<int,int>con[N];        
    
    struct node { 
        int ch[2],rev,f; 
        ll s0[2],s1[2],s2[2],tag,v,size; 
    }s[N];          
    
    void Pushup(int x) 
    {           
        s[x].size=s[lson].size+s[rson].size+1;  
        s[x].s0[0]=s[lson].s0[0]+s[rson].s0[0]+s[x].v;     
        s[x].s1[0]=s[lson].s1[0]+s[rson].s1[0]+(s[rson].s0[0]+s[x].v)*(s[lson].size+1);        
        s[x].s2[0]=s[s[x].ch[0]].s2[0]+s[s[x].ch[1]].s2[0]+(s[s[x].ch[1]].s0[0]+s[x].v)*(s[s[x].ch[0]].size+1)*(s[s[x].ch[0]].size+1)+2ll*s[s[x].ch[1]].s1[0]*(s[s[x].ch[0]].size+1);      
        s[x].s0[1]=s[lson].s0[1]+s[rson].s0[1]+s[x].v;   
        s[x].s1[1]=s[rson].s1[1]+s[lson].s1[1]+(s[lson].s0[1]+s[x].v)*(s[rson].size+1);        
        s[x].s2[1]=s[s[x].ch[1]].s2[1]+s[s[x].ch[0]].s2[1]+(s[s[x].ch[0]].s0[1]+s[x].v)*(s[s[x].ch[1]].size+1)*(s[s[x].ch[1]].size+1)+2ll*s[s[x].ch[0]].s1[1]*(s[s[x].ch[1]].size+1);       
    } 
    
    void Up_tag(int x,ll v) 
    {      
        s[x].v+=v;      
        s[x].tag+=v;  
        s[x].s0[0]+=s[x].size*v;        
        s[x].s0[1]+=s[x].size*v;          
        s[x].s1[0]+=calc1(s[x].size)*v; 
        s[x].s1[1]+=calc1(s[x].size)*v;        
        s[x].s2[0]+=calc2(s[x].size)*v;   
        s[x].s2[1]+=calc2(s[x].size)*v;   
    }  
    
    void Up_rev(int x) 
    {  
        s[x].rev^=1; 
        swap(lson,rson); 
        swap(s[x].s0[0],s[x].s0[1]); 
        swap(s[x].s1[0],s[x].s1[1]),swap(s[x].s2[0],s[x].s2[1]);   
    }  
    
    void Pushdown(int x) 
    { 
        if(s[x].tag) 
        {
            if(lson) Up_tag(lson,s[x].tag); 
            if(rson) Up_tag(rson,s[x].tag); 
            s[x].tag=0; 
        }
        if(s[x].rev) 
        {
            if(lson) Up_rev(lson); 
            if(rson) Up_rev(rson);    
            s[x].rev=0;        
        }
    }  
    
     
    void rotate(int x) 
    {    
        int old=s[x].f,fold=s[old].f,which=get(x);   
        if(!Isr(old)) s[fold].ch[s[fold].ch[1]==old]=x;     
        s[old].ch[which]=s[x].ch[which^1]; 
        if(s[old].ch[which]) s[s[old].ch[which]].f=old; 
        s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold; 
        Pushup(old),Pushup(x); 
    }
    
    void Splay(int x) 
    {     
        int v=0,u=x,fa; 
        for(sta[++v]=u;!Isr(u);u=s[u].f)  sta[++v]=s[u].f;  
        for(;v;--v)  Pushdown(sta[v]);   
        for(u=s[u].f;(fa=s[x].f)!=u;rotate(x))   
        {   
            if(s[fa].f!=u) 
                rotate(get(fa)==get(x)?fa:x);
        }
    }           
    
    void Access(int x) 
    {
        for(int y=0;x;y=x,x=s[x].f)  
        {
            Splay(x);     
            rson=y; 
            Pushup(x);  
        }
    }
    
    void Make_Root(int x) 
    {
        Access(x); 
        Splay(x); 
        Up_rev(x);   
    }
    
    void Link_Edge(int x,int y) 
    {    
        Access(x),Splay(x); 
        Make_Root(y);   
        s[y].f=x;   
    }    
    
    void Cut_Edge(int x,int y) 
    {     
        Make_Root(x),Access(y),Splay(y);    
        if(!s[x].ch[1]&&s[y].ch[0]==x)   s[y].ch[0]=s[x].f=0;            
        Pushup(y);           
    }
    
    void Split(int x,int y) 
    {
        Make_Root(x),Access(y),Splay(y);      
    }
    
    int Find_Root(int x) 
    {   
        while(s[x].f) x=s[x].f;  
        return x;   
    }       
    
    int main() 
    { 
        // IO::setIO("input"); 
        int i,j,n,m; 
        scanf("%d%d",&n,&m);       
        for(i=1;i<=n;++i)  scanf("%lld",&s[i].v),Pushup(i); 
        for(i=1;i<n;++i) 
        {
            int x,y; 
            scanf("%d%d",&x,&y); 
            Link_Edge(x,y); 
            con[x][y]=con[y][x]=1; 
        }
        for(i=1;i<=m;++i) 
        {
            int op,x,y,z; 
            scanf("%d",&op); 
            if(op==1) 
            {    
                scanf("%d%d",&x,&y);           
                if(!con[x][y])  continue;   
                else 
                {
                    Cut_Edge(x,y);    
                    con[x][y]=con[y][x]=0; 
                }
            }
            if(op==2) 
            {    
                scanf("%d%d",&x,&y); 
                if(Find_Root(x)==Find_Root(y))  continue;        
                else 
                {
                    con[x][y]=con[y][x]=1;    
                    Link_Edge(x,y);            
                }
            }
            if(op==3) 
            {
                scanf("%d%d%d",&x,&y,&z);   
                if(Find_Root(x)!=Find_Root(y)) continue;        
                Split(x,y);      
                Up_tag(y,(ll)z);                       
            }
            if(op==4)                          
            {
                scanf("%d%d",&x,&y);     
                if(Find_Root(x)!=Find_Root(y)) printf("-1
    "); 
                else 
                {
                    Split(x,y);                    
                    ll dn=s[y].size*(s[y].size+1)/2;                               
                    ll up=(s[y].size+1ll)*s[y].s1[0]-s[y].s2[0];  
                    ll g=gcd(up,dn); 
                    printf("%lld/%lld
    ",up/g,dn/g);    
                }   
            }
        }
        return 0;
    }    
    

      

  • 相关阅读:
    百度地图API-自定义图标覆盖物
    笔记-前端学习路线
    当div自适应的高度超过预设的高度的时候出现滚动条的办法
    有关前端的书籍
    js-方法
    正在进行中
    ARM的启动和中断向量表
    ARM中的总线
    NOR FLASH与NAND FLASH的区别
    ARM流水线关键技术分析与代码优化
  • 原文地址:https://www.cnblogs.com/guangheli/p/12121565.html
Copyright © 2011-2022 走看看