zoukankan      html  css  js  c++  java
  • UOJ#207. 共价大爷游长沙

    如果不断边,直接路径+,看边的权值。

    这个相当于是区间加,单点查询

    如果断边,很多路径变化了,就凉了。

    考虑单点加,查询子树内部有没有包含所有的路径的一端。

    考虑hash

    给两端xor同一个随机值。

    这样,子树没有出现或者出现两次都不合法,贡献都是0

    出错概率就是每个点都是随机情况下,存在一个子集xor为0

    概率很小

    单点加,区间查询

    其实链处理也是可以的

    画画情况发现每个经过(u,v)的都恰好还是对的

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    #define ui unsigned int 
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    namespace Modulo{
    const int mod=998244353;
    il int ad(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    il int sub(int x,int y){return ad(x,mod-y);}
    il int mul(int x,int y){return (ll)x*y%mod;}
    il void inc(int &x,int y){x=ad(x,y);}
    il void inc2(int &x,int y){x=mul(x,y);}
    il int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
    template<class ...Args>il int ad(const int a,const int b,const Args &...args) {return ad(ad(a,b),args...);}
    template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);}
    }
    // using namespace Modulo;
    namespace Miracle{
    const int N=1e5+5;
    int n,m;
    struct node{
        int ch[2],fa;
        int rev;
        ui val,sum;
        ui si;
    }t[N];
    bool nrt(int x){
        return ((t[t[x].fa].ch[0]==x)||(t[t[x].fa].ch[1]==x));
    }
    void pushup(int x){
        t[x].sum=t[t[x].ch[0]].sum^t[t[x].ch[1]].sum^t[x].val^t[x].si;
    }
    #define ls t[x].ch[0]
    #define rs t[x].ch[1]
    void rev(int x){
        swap(ls,rs);
        t[x].rev^=1;
    }
    void pushdown(int x){
        if(t[x].rev){
            rev(ls);rev(rs);
            t[x].rev=0;
        }
    }
    void rotate(int x){
        int y=t[x].fa,d=t[y].ch[1]==x;
        t[t[y].ch[d]=t[x].ch[!d]].fa=y;
        if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
        else t[x].fa=t[y].fa;
        t[t[x].ch[!d]=y].fa=x;
        pushup(y);
    }
    int sta[N];
    void splay(int x){
        int y=x,z=0;
        sta[++z]=y;
        while(nrt(y)) y=t[y].fa,sta[++z]=y;
        while(z) pushdown(sta[z--]);
        
        while(nrt(x)){
            y=t[x].fa,z=t[y].fa;
            if(nrt(y)){
                rotate((t[y].ch[0]==x)==(t[z].ch[0]==y)?y:x);
            }
            rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(reg y=0;x;y=x,x=t[x].fa){
            splay(x);
            t[x].si^=t[y].sum;
            t[x].si^=t[t[x].ch[1]].sum;
            t[x].ch[1]=y;
            pushup(x);
        }
    }
    void makert(int x){
        access(x);splay(x);rev(x);
    }
    void split(int x,int y){
        makert(x);access(y);splay(y);
    }
    void link(int x,int y){
        split(x,y);
        t[x].fa=y;
        t[y].si^=t[x].sum;
        pushup(y);
    }
    void cut(int x,int y){
        split(x,y);
        t[x].fa=t[y].ch[0]=0;pushup(y);
    }
    void tag(int x,int c){
        access(x);splay(x);
        t[x].val^=c;pushup(x);
    }
    struct path{
        int x,y;
        ui val;
    }p[3*N];
    int cnt;
    ui tot;
    
    vector<int>to[N];
    void dfs(int x,int fa){
        for(solid y:to[x]){
    //        int y=e[i].to;
            if(y==fa) continue;
            t[y].fa=x;
            dfs(y,x);
        }
    }
    ui Rand(){
        ui le=(rand()<<1)|(rand()&1);
        ui ri=(rand()<<1)|(rand()&1);
        return (le<<16)|ri;
    }
    int main(){
        srand((unsigned long long)new char);
        int haha;rd(haha);
        rd(n);rd(m);
        int x,y;
        for(reg i=1;i<n;++i){
            rd(x);rd(y);
            to[x].pb(y);to[y].pb(x);
        }
        dfs(1,0);
        
        int op,u,v;
        while(m--){
            rd(op);
            if(op==1){    
                rd(x);rd(y);rd(u);rd(v);
                cut(x,y);link(u,v);
            }else if(op==2){
                rd(x);rd(y);
                ++cnt;
                p[cnt].x=x;p[cnt].y=y;
                p[cnt].val=Rand();
                
                tot^=p[cnt].val;
                tag(x,p[cnt].val);
                tag(y,p[cnt].val);
            }else if(op==3){
                int id;
                rd(id);
                x=p[id].x,y=p[id].y;
                ui val=p[id].val;
                
                tot^=val;
                tag(x,val);
                tag(y,val);
            }else{
                rd(x);rd(y);
                split(x,y);
                if(t[x].sum==tot){
                    puts("YES");
                }else puts("NO");
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */

     注意,link的时候,

    必须access(y),splay(y),因为要更新y的si值。作为根pushup才行

  • 相关阅读:
    innodb next-key lock
    kafka-0.9
    aggregations 详解1(概述)
    mapping 详解5(dynamic mapping)
    mapping 详解4(mapping setting)
    mapping 详解3(Meta-Fields)
    mapping 详解2(field datatypes)
    mapping 详解1(mapping type)
    分布式 ES 操作流程解析
    ES 中的那些坑
  • 原文地址:https://www.cnblogs.com/Miracevin/p/11070506.html
Copyright © 2011-2022 走看看