• #207. 共价大爷游长沙


    题目描述

    http://uoj.ac/problem/207

    题解

    因为这道题有删边和加边的操作,所以我们不能再链上操作,只能在点上操作。

    考虑一些正确性玄学的算法。

    我们给每一次链加随机一个权值,这样对于每次询问就查一下这条边分成的两块中的权值异或和是否等于当前所有链的权值异或和即可。

    注意维护虚子树时link要先split。

    考虑这个做法的正确性,那么就是一个集合的异或和为0的概率,它是权值分之1,所以错的概率很小。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib> 
    #define ls ch[x][0]
    #define rs ch[x][1]
    #define N 100009
    using namespace std;
    int ch[N][2],sum,size[N],si[N],a[N],fa[N],n,m,top;
    bool rev[N];
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x; 
    }
    inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    inline bool ge(int x){return ch[fa[x]][1]==x;}
    inline void pushup(int x){size[x]=size[ls]^size[rs]^si[x]^a[x];}
    inline void rotate(int x){
        int y=fa[x],o=ge(x);
        ch[y][o]=ch[x][o^1];fa[ch[y][o]]=y;
        if(!isroot(y))ch[fa[y]][ge(y)]=x;fa[x]=fa[y];
        fa[y]=x;ch[x][o^1]=y;pushup(y);pushup(x);
    }
    void pushdown(int x){if(rev[x])rev[ls]^=1,rev[rs]^=1,rev[x]^=1,swap(ls,rs);}
    void _pushdown(int x){if(!isroot(x))_pushdown(fa[x]);pushdown(x);}
    inline void splay(int x){
        _pushdown(x);
        while(!isroot(x)){
            int y=fa[x];
            if(isroot(y))rotate(x);
            else rotate(ge(x)==ge(y)?y:x),rotate(x);
        }
    }
    inline void access(int x){
        for(int y=0;x;y=x,x=fa[x]){
            splay(x);
            si[x]^=size[y];si[x]^=size[ch[x][1]];
            ch[x][1]=y;
            pushup(x);
        }
    }
    inline void makeroot(int x){access(x);splay(x);rev[x]^=1;}
    inline void split(int x,int y){makeroot(x);access(y);splay(y);}
    inline void link(int x,int y){
        split(x,y);
        fa[x]=y;si[y]^=size[x];pushup(y);
    }
    inline void cut(int x,int y){
        split(x,y);
        ch[y][0]=fa[x]=0;
        pushup(y);
    }
    struct node{int u,v,w;}st[N*3];
    int main(){
        int id=rd();
        srand(19260928);
        n=rd();m=rd();
        int x,y,u,v,w;
        for(int i=1;i<n;++i){
            x=rd();y=rd();
            link(x,y);
        }
        while(m--){
            int opt=rd();
            if(opt==1){
                x=rd();y=rd();u=rd();v=rd();
                cut(x,y);link(u,v); 
            }
            else if(opt==2){
                x=rd();y=rd();w=rand();sum^=w;
                st[++top]=node{x,y,w};
                makeroot(y);
                a[y]^=w;pushup(y);
                access(x);splay(x);
                a[x]^=w;pushup(x);
            }
            else if(opt==3){
                x=rd();sum^=st[x].w;u=st[x].u;v=st[x].v;
                makeroot(v);
                a[v]^=st[x].w;pushup(v);
                access(u);splay(u);
                a[u]^=st[x].w;pushup(u);
            }
            else{
                x=rd();y=rd();
                split(x,y);
                if((size[y]^size[x])!=sum){puts("NO");continue;}
                if(size[x]!=sum){puts("No");continue;}
                puts("YES");
            }
        }
    
        return 0;
    }
  • 相关阅读:
    基本数据类型(int, bool, str)
    万恶之源之运算符
    python基础初识
    leetcode 653. Two Sum IV
    leetcode 16 3Sum Closest
    leetcode15 3Sum
    leetcode 1 Two Sum
    【站立会议】第四天
    【站立会议】第三天
    【站立会议】第二天
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10421533.html
Copyright © 2020-2023  润新知