LOJ #558. 「Antileaf's Round」我们的 CPU 遭到攻击 LCT维护子树信息

这个和 QTREE5 的套路是一样的,就是维护一个深度最深/浅的距离和,然后合并一下就好了. 

code: 

#include <map>
#include <string> 
#include <cstdio>    
#include <cstring>  
#include <algorithm>

#define N 400008 
#define ll long long 

using namespace std; 

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);    
    }
}; 
 
namespace LCT {     

    #define lson t[x].ch[0] 
    #define rson t[x].ch[1] 
    #define get(x) (t[t[x].f].ch[1]==x)  
    #define Isr(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x))    

    struct node { 
        int ch[2],rev,f,is_black;         
        ll son_size,son_dis;   
        ll size,ldis,rdis,dis,val;   
    }t[N];              
    int sta[N];  

    void Pushup(int x) 
    {     
        t[x].size=t[lson].size+t[rson].size+t[x].son_size;    
        t[x].dis=t[lson].dis+t[rson].dis+t[x].val;        
        t[x].ldis=t[lson].ldis+t[rson].ldis+t[x].son_dis+(t[x].son_size+t[rson].size)*(t[x].dis-t[rson].dis);
        t[x].rdis=t[rson].rdis+t[lson].rdis+t[x].son_dis+(t[x].son_size+t[lson].size)*(t[x].dis-t[lson].dis);
    }           

    void Mark_rev(int x) 
    { 
        t[x].rev^=1; 
        swap(lson,rson);
        swap(t[x].ldis,t[x].rdis);                 
    } 

    void Pushdown(int x) 
    {
        if(t[x].rev) 
        {
            if(lson)   Mark_rev(lson); 
            if(rson)   Mark_rev(rson);  
            t[x].rev^=1;   
        }
    } 

    void Rotate(int x) 
    {
        int old=t[x].f,fold=t[old].f,which=get(x);  
        if(!Isr(old)) t[fold].ch[t[fold].ch[1]==old]=x;   
        t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;     
        t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; 
        Pushup(old),Pushup(x); 
    }

    void Splay(int x) 
    {   
        int v=0,u=x,fa; 
        for(sta[++v]=u;!Isr(u);u=t[u].f)  sta[++v]=t[u].f;   
        for(;v;--v)  Pushdown(sta[v]); 
        for(u=t[u].f;(fa=t[x].f)!=u;Rotate(x)) 
            if(t[fa].f!=u) 
                Rotate(get(fa)==get(x)?fa:x);  
    }

    void Access(int x) 
    {   
        for(int y=0;x;y=x,x=t[x].f) 
        {
            Splay(x);    
            if(rson)   
            {         
                t[x].son_size+=t[rson].size;   
                t[x].son_dis+=t[rson].ldis;   
            }   
            if(y) 
            {
                t[x].son_size-=t[y].size;    
                t[x].son_dis-=t[y].ldis;   
            }
            rson=y;   
            Pushup(x); 
        }
    }   

    void Make_Root(int x) 
    {  
        Access(x),Splay(x),Mark_rev(x); 
    }      

    void Link_Edge(int x,int y) 
    {   
        Access(x),Splay(x); 
        Make_Root(y);   
        t[y].f=x;    
        t[x].son_size+=t[y].size;   
        t[x].son_dis+=t[y].ldis;   
    }

    void Cut_Edge(int x,int y) 
    {    
        Make_Root(x); 
        Access(y),Splay(y);    
        t[y].ch[0]=t[x].f=0;   
        Pushup(y);   
    }   

}; 

map<int,int>tr[N];   

int main() 
{ 
    // IO::setIO("input");  
    using namespace LCT;   
    int i,j,n,m,q,tot;   
    scanf("%d%d%d",&n,&m,&q);       
    tot=n;   
    for(i=1;i<=m;++i) 
    {   
        int x,y,w; 
        scanf("%d%d%d",&x,&y,&w);             
        tr[x][y]=tr[y][x]=++tot;       
        LCT::t[tot].val=w;
        LCT::Link_Edge(x,tot);  
        LCT::Link_Edge(y,tot);   
    }          
    for(i=1;i<=q;++i) 
    { 
        char str[3];  
        scanf("%s",str);   
        if(str[0]=='L') 
        {  
            int x,y,w; 
            scanf("%d%d%d",&x,&y,&w);    
            tr[x][y]=tr[y][x]=++tot;    
            LCT::t[tot].val=w;   
            LCT::Link_Edge(x,tot); 
            LCT::Link_Edge(y,tot);  
        } 
        if(str[0]=='C') 
        {     
            int x,y,key=0; 
            scanf("%d%d",&x,&y);  
            key=tr[x][y];    
            LCT::Cut_Edge(x,key); 
            LCT::Cut_Edge(y,key);   
        } 
        if(str[0]=='F')
        {      
            int x; 
            scanf("%d",&x);    
            LCT::Access(x); 
            LCT::Splay(x);   
            LCT::t[x].is_black^=1;    
            if(LCT::t[x].is_black==0)  
            {
                --t[x].son_size; 
            }
            else 
            {
                ++t[x].son_size;   
            }
            LCT::Pushup(x); 
        } 
        if(str[0]=='Q') 
        {      
            int x; 
            scanf("%d",&x);        
            LCT::Make_Root(x);   
            Access(x);                      
            printf("%lld\n",LCT::t[x].son_dis);   
        }
    }
    return 0; 
}

  

上一篇:矩阵求导笔记


下一篇:linux下使用 du查看某个文件或目录占用磁盘空间的大小