zoukankan      html  css  js  c++  java
  • BZOJ 3553: [Shoi2014]三叉神经树 LCT

    犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号.

    但是没有想到这个东西可以直接维护.

    假设不考虑叶子节点,那么如果当前点的值是 1 的话要求儿子节点权和 > 1

    假设当前从 0->1,那么该叶子造成的影响一定是一条向上的链.

    如果向上走到某一时刻,该点的儿子权和不等于 1,那么这个点及以上就影响不到了.

    如果权和为 2,那么在 0->1 之前就已经是 1 了,修改后也肯定还是 1.

    如果权和为 0,那么在 0->1 之后顶多能把权和+1,所以做的时无用功.

    所以,会造成影响的是以该叶子向上延伸的最长的全 1 链.

    这些点全部会从 0 变成 1,然后做一个区间 +1 (全变成 2)

    这里讲一下区间加的时候如何维护标记:

    因为我们进行区间加的链肯定是全 1 / 2 的.

    所以说,原来是全 1 的话原来的 1 的最深节点就消失,然后最深度节点是 2 的就会新产生.

    然后你发现正好是 1->2, 2->0 或者 2->1, 1->0,所以直接交换一下 1 和 2 的编号即可.

    #include <bits/stdc++.h>    
    using namespace std; 
    #define N 1600000   
    #define lson t[x].ch[0] 
    #define rson t[x].ch[1] 
    #define get(x)  (t[t[x].f].ch[1]==x)   
    #define isrt(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x))   
    #define setIO(s) freopen(s".in","r",stdin) 
    int n,m,edges; 
    int hd[N],to[N],nex[N],sta[N];   
    struct node 
    {
        int ch[2],id[3],f,add,val,sum;    
    }t[N];      
    inline void mark(int x,int add) 
    {
        if(!x) return;   
        t[x].sum+=add,t[x].val=t[x].sum>1;  
        swap(t[x].id[1],t[x].id[2]);    
        t[x].add+=add;   
    }
    inline void pushup(int x) 
    {              
        t[x].id[1]=t[rson].id[1]; 
        t[x].id[2]=t[rson].id[2];  
        if(!t[x].id[1]) 
        {
            if(t[x].sum!=1)  t[x].id[1]=x; 
            else t[x].id[1]=t[lson].id[1];          
        } 
        if(!t[x].id[2]) 
        {
            if(t[x].sum!=2)  t[x].id[2]=x;  
            else t[x].id[2]=t[lson].id[2]; 
        }
    }
    inline void pushdown(int x) 
    { 
        if(t[x].add) 
        {
            if(lson)   mark(lson,t[x].add); 
            if(rson)   mark(rson,t[x].add); 
            t[x].add=0;   
        }
    }
    inline void rotate(int x) 
    {
        int old=t[x].f,fold=t[old].f,which=get(x);  
        if(!isrt(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 u=x,v=0,fa;  
        for(sta[++v]=u;!isrt(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); 
            }
        }
    }
    inline void Access(int x) 
    {
        for(int y=0;x;y=x,x=t[x].f) 
        {
            splay(x); 
            rson=y; 
            pushup(x);  
        }
    }
    void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;  
    }
    void dfs(int u) 
    {
        for(int i=hd[u];i;i=nex[i])    dfs(to[i]),t[u].sum+=t[to[i]].val;    
        if(u<=n) t[u].val=t[u].sum>1;         
    }   
    int main() 
    {   
        // setIO("input"); 
        int i,j,Q; 
        scanf("%d",&n); 
        for(i=1;i<=n;++i) 
        {
            for(j=1;j<=3;++j)  
            {
                int x; 
                scanf("%d",&x),add(i,x),t[x].f=i;         
            }
        }   
        for(i=n+1;i<=3*n+1;++i)    scanf("%d",&t[i].val);                 
        dfs(1); 
        scanf("%d",&Q);   
        int ans=t[1].val;   
        while(Q--) 
        {
            int x; 
            scanf("%d",&x);                 
            int tag=(t[x].val?-1:1),y=t[x].f;   
            Access(y),splay(y);  
            int w=t[y].id[t[x].val?2:1];                                   
            if(w) 
            {
                splay(w);   
                mark(t[w].ch[1],tag);      
                pushup(t[w].ch[1]);    
                t[w].sum+=tag; 
                t[w].val=t[w].sum>1; 
                pushup(w); 
            } 
            else 
            {
                ans^=1;  
                mark(y,tag); 
                pushup(y); 
            } 
            t[x].val^=1; 
            printf("%d
    ",ans);  
        }
        return 0;     
    }
    

      

  • 相关阅读:
    git 学习
    公司领导写给新员工的信
    PLSQl远程连接oracle数据库
    hdu2222之AC自动机入门
    代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性
    ubuntu13.04安装SenchaArchitect-2.2无法启动的问题
    MVVMLight Toolkit在Windows Phone中的使用扩展之一:在ViewModel中实现导航,并传递参数
    面试题24:二叉搜索树与双向链表
    Struts2中的包的作用描述
    filter-mapping中的dispatcher使用
  • 原文地址:https://www.cnblogs.com/guangheli/p/11953427.html
Copyright © 2011-2022 走看看