zoukankan      html  css  js  c++  java
  • luogu 5354 [Ynoi2017]由乃的OJ LCT+位运算

    如果做过起床困难综合征的话应该很快就能有思路,没做过那道题的话还真是挺费劲的. 

    我们不知道要带入的值是什么,但是我们可以知道假设带入值得当前位为 $1$ 时这一位在经过位运算后是否为 $1$.

    至于这个怎么维护,我们开两个变量 $f0,f1$ 代表初始带入全 $0$,全 $1$ 时每一位得值.

    然后在 $LCT$ 中维护从左向右,从右向左两个方向上得这个东西,注意一下 $pushup$ 函数得写法. 

    这段代码十分优美,利用了按位取反等骚操作: 

    struct node 
    {    
        ll f0,f1;   
        node operator+(const node &b) const 
        {
            node a; 
            a.f0=(~f0&b.f0)|(f0&b.f1);      
            a.f1=(~f1&b.f0)|(f1&b.f1);   
            return a; 
        }
    }f[N],L[N],R[N];   
    

    code:

    #include <bits/stdc++.h> 
    #define N 100007     
    #define ll unsigned long long 
    #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)    
    using namespace std; 
    int n,m,k,edges; 
    int hd[N],to[N<<1],nex[N<<1];  
    void addedge(int u,int v) 
    { 
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;     
    } 
    struct node 
    {    
        ll f0,f1;   
        node operator+(const node &b) const 
        {
            node a; 
            a.f0=(~f0&b.f0)|(f0&b.f1);      
            a.f1=(~f1&b.f0)|(f1&b.f1);   
            return a; 
        }
    }f[N],L[N],R[N];    
    struct Link_Cut_Tree
    {   
        #define lson p[x].ch[0] 
        #define rson p[x].ch[1] 
        int sta[N];   
        struct Node 
        {    
            int ch[2],f,rev;            
        }p[N];     
        int get(int x) 
        {
            return p[p[x].f].ch[1]==x; 
        }
        int isrt(int x) 
        {
            return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x); 
        }      
        void pushup(int x) 
        {
            L[x]=R[x]=f[x];  
            if(lson) L[x]=L[lson]+L[x], R[x]=R[x]+R[lson];     
            if(rson) L[x]=L[x]+L[rson], R[x]=R[rson]+R[x];     
        }
        void rotate(int x) 
        {
            int old=p[x].f,fold=p[old].f,which=get(x);  
            if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x;   
            p[old].ch[which]=p[x].ch[which^1],p[p[old].ch[which]].f=old; 
            p[x].ch[which^1]=old,p[old].f=x,p[x].f=fold; 
            pushup(old),pushup(x); 
        }
        void mark(int x) 
        {
            if(!x) return; 
            swap(lson,rson), swap(L[x],R[x]),p[x].rev^=1;  
        }
        void pushdown(int x) 
        {
            if(p[x].rev) 
            { 
                p[x].rev=0; 
                if(lson) mark(lson); 
                if(rson) mark(rson); 
            } 
        }
        void splay(int x) 
        {
            int u=x,v=0,fa; 
            for(sta[++v]=u;!isrt(u);u=p[u].f) sta[++v]=p[u].f;  
            for(;v;--v) pushdown(sta[v]);   
            for(u=p[u].f;(fa=p[x].f)!=u;rotate(x)) 
                if(p[fa].f!=u) 
                    rotate(get(fa)==get(x)?fa:x);   
        }
        void Access(int x) 
        {
            for(int y=0;x;y=x,x=p[x].f) 
            {
                splay(x);  
                rson=y; 
                pushup(x);  
            }
        }
        void makeroot(int x) 
        {
            Access(x),splay(x),mark(x); 
        } 
        void split(int x,int y) 
        {
            makeroot(x), Access(y), splay(y);  
        }   
        void link(int x,int y)
        { 
            makeroot(x), p[x].f=y;    
        }     
        void cut(int x,int y) 
        {
            makeroot(x),Access(y),splay(y);  
            p[y].ch[0]=p[x].f=0;  
            pushup(y);    
        }  
        #undef lson 
        #undef rson  
    }lct;  
    void solve(int x,int y,ll z) 
    {
        lct.split(x,y);    
        int i;   
        ll re=0;    
        for(i=k-1;i>=0;--i) 
        { 
            if(L[y].f0&(1ll<<i)) re+=(1ll<<i);   
            else if((L[y].f1&(1ll<<i)) && (1ll<<i)<=z) re+=(1ll<<i), z-=(1ll<<i);      
        } 
        printf("%llu
    ",re);    
    }      
    void dfs(int u,int ff) 
    { 
        lct.p[u].f=ff;     
        for(int i=hd[u];i;i=nex[i])     
            if(to[i]!=ff) dfs(to[i],u);
    }  
    int main() 
    { 
        int i,j;   
        // setIO("input"); 
        scanf("%d%d%d",&n,&m,&k);       
        for(i=1;i<=n;++i) 
        {
            int op; 
            ll y; 
            scanf("%d%llu",&op,&y);    
            if(op==1) f[i]=(node){0ll,y};   
            if(op==2) f[i]=(node){y,~0ll};      
            if(op==3) f[i]=(node){y,~y}; 
            lct.pushup(i);          
        }
        for(i=1;i<n;++i) 
        {   
            int u,v; 
            scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);    
        }              
        dfs(1,0);    
        for(i=1;i<=m;++i) 
        {
            int op; 
            scanf("%d",&op); 
            if(op==1) 
            {
                int x,y; 
                ll z; 
                scanf("%d%d%llu",&x,&y,&z);     
                solve(x,y,z);   
            }
            else 
            {
                int x,y; 
                ll z; 
                scanf("%d%d%llu",&x,&y,&z);       
                lct.Access(x); 
                lct.splay(x);  
                if(y==1) f[x]=(node){0ll,z};     
                if(y==2) f[x]=(node){z,~0ll};  
                if(y==3) f[x]=(node){z,~z};        
                lct.pushup(x);          
            }
        }
        return 0;     
    }
    

      

  • 相关阅读:
    IDEA常用快捷键和设置
    java反射总结
    IO编程总结
    3月份主要学习
    idea中maven将jar包导入本地maven库
    hive常用命令
    CentOS7 安装图形化桌面
    vue+leaflet
    Springboot + Rabbitmq + WebSocet + vue
    VUE 中引入百度地图(vue-Baidu-Map)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11648691.html
Copyright © 2011-2022 走看看