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('\n');}
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*
*/

猜你喜欢

转载自www.cnblogs.com/Miracevin/p/11070506.html
今日推荐