• luoguP6018 [Ynoi2010]Fusion tree 01trie


    今年省选考了这个技巧,感觉之前没做过类似的题的话现场挺难想出来的.       

    我们发现对 1 个数 +1 可以看作从低到高位的第一个 0 修改成 1,该 0 后面的 1 修改成 0.             

    将一个节点的所有儿子对应的数放到该节点对应的 01 trie 中进行修改的话就是将 0,1 翻转.         

    翻转后走 0 那边,然后递归地进行翻转就行.    

    然后注意在插入地时候即使 v=0 也要一直递归下去,因为我们是从低位向高位进行插入.   

    code:  

    #include <cstdio>  
    #include <algorithm> 
    #include <cstring>        
    #define MA 20  
    #define N 1000009
    #define ll long long
    #define lson s[x].ch[0]
    #define rson s[x].ch[1]
    #define setIO(s) freopen(s".in","r",stdin)
    using namespace std;       
    int n,m,edges,tot; 
    int hd[N],to[N<<1],nex[N<<1],fa[N],rt[N],a[N],addv[N];         
    struct data {  
        int si,sum,cur,ch[2];  
    }s[N*30];     
    void pushup(int x) {             
        s[x].sum=s[lson].sum^s[rson].sum;       
        if(s[rson].si&1) s[x].sum+=1<<s[rson].cur;             
    }
    void ins(int x,int v,int cur) {  
        if(cur>20) return;  
        if(v&1) {  
            if(!rson) {
                rson=++tot;            
                s[rson].cur=cur;         
            }        
            ++s[rson].si;  
            ins(rson,v>>1,cur+1);                          
        }  
        else {                    
            if(!lson) {          
                lson=++tot; 
                s[lson].cur=cur; 
            }         
            ++s[lson].si; 
            ins(lson,v>>1,cur+1); 
        }  
        pushup(x); 
    }          
    void del(int x,int v,int cur=0) {  
        if(cur>20) return;  
        if(v&1) { 
            --s[rson].si; 
            del(rson,v>>1,cur+1); 
        } 
        else {     
            --s[lson].si; 
            del(lson,v>>1,cur+1); 
        }  
        pushup(x);   
    }    
    void upd(int x) {  
        if(!x) return;         
        swap(lson,rson),upd(lson),pushup(x);           
    } 
    void add(int u,int v) { 
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    }  
    void dfs(int x,int ff) {   
        fa[x]=ff; 
        for(int i=hd[x];i;i=nex[i]) if(to[i]!=ff) dfs(to[i],x); 
    }       
    char *p1,*p2,buf[100000];  
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)   
    int rd() {  
        char c;  int x=0; 
        do { c=nc(); } while(c<48);    
        while(c>47) { 
            x=(((x<<2)+x)<<1)+(c^48),c=nc(); 
        }  
        return x;  
    }
    int main() {  
        // setIO("input");     
        // freopen("input.out","w",stdout); 
        int x,y,z;  
        n=rd(),m=rd();  
        for(int i=1;i<n;++i) {  
            x=rd(),y=rd();  
            add(x,y),add(y,x); 
        }     
        for(int i=1;i<=n;++i) a[i]=rd();   
        dfs(1,0); 
        for(int i=1;i<=n;++i) {                    
            rt[i]=++tot; 
            for(int j=hd[i];j;j=nex[j]) {   
                y=to[j]; 
                if(y==fa[i]) continue;   
                ins(rt[i],a[y],0);      
            }  
        } 
        int op; 
        for(int i=1;i<=m;++i) { 
            op=rd(); 
            if(op==1) { 
                x=rd();  
                upd(rt[x]);        
                if(fa[x]) { 
                    z=fa[fa[x]];  
                    if(z) {                      
                        del(rt[z],a[fa[x]]+addv[z]); 
                        ins(rt[z],a[fa[x]]+addv[z]+1,0);    
                    }        
                    ++a[fa[x]];    
                }             
                ++addv[x];    
            }
            if(op==2) {       
                x=rd(),y=rd();  
                if(fa[x]) { 
                    del(rt[fa[x]],a[x]+addv[fa[x]]);        
                    ins(rt[fa[x]],a[x]+addv[fa[x]]-y,0);  
                }  
                a[x]-=y;  
            }
            if(op==3) {             
                x=rd();           
                printf("%d
    ",s[rt[x]].sum^(a[fa[x]]+addv[fa[fa[x]]]));    
            }       
        }    
        return 0; 
    }   
    

      

  • 相关阅读:
    java继承中的初始化顺序
    java可访问修饰符
    java简单数据类型转化
    java运算符优先级
    面向切面编程的例子
    什么是面向切面编程
    return 的使用
    通过修改my.ini配置文件来解决MySQL 5.6 内存占用过高的问题
    spring 注入使用注解(不用xml)
    spring在扫描包中的注解类时出现Failed to read candidate component错误
  • 原文地址:https://www.cnblogs.com/guangheli/p/13293337.html
Copyright © 2020-2023  润新知