#207. 共价大爷游长沙

分析

因为我们要维护,删边,加边。所以我们考虑使用 。那么现在就是求问一条边是否被所有路径经过。所以我们考虑用子集异或。那么我们 之后,节点 的子树中的异或和必须等于 。所以我们还有维护虚子树。如果能分析到异或。这道题就不难了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
const int N = 610000;
ull rnd[N],val[N],s1[N],s2[N];
int ch[N][2],L[N],R[N],fa[N],n,m;
bool r[N];
int read() {
    int x = 0,f = 0;char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-')f = 1;ch = getchar();}
    while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
    return f ? -x : x;
}
bool nroot(int x) {return ch[fa[x]][1] == x || ch[fa[x]][0] == x;}
void pushup(int x) {s1[x] = val[x] ^ s1[ch[x][1]] ^ s1[ch[x][0]] ^ s2[x];}
void pushr(int x) {swap(ch[x][1],ch[x][0]);r[x] ^= 1;}
void pushdown(int x) {
    if(r[x]) {
        if(ch[x][1]) pushr(ch[x][1]);
        if(ch[x][0]) pushr(ch[x][0]);
        r[x] = 0;
    }
}
void rotate(int x) {
    int y = fa[x],z = fa[y],k = (ch[y][1]==x),w = ch[x][!k];
    if(nroot(y)) ch[z][ch[z][1]==y] = x;ch[x][!k] = y;ch[y][k] = w;
    if(w) fa[w] = y;fa[x] = z;fa[y] = x;pushup(y);
}
void push(int x) {if(nroot(x)) push(fa[x]);pushdown(x);}
void splay(int x) {
    push(x);while(nroot(x)) {
        int y = fa[x],z = fa[y];if(nroot(y)) rotate(((ch[y][1]==x)^(ch[z][1]==y))?x:y);
        rotate(x);pushup(x);
    }
}
void access(int x) {
    for(int y = 0;x;x = fa[y=x]) {
        splay(x);s2[x] ^= s1[y] ^ s1[ch[x][1]];ch[x][1] = y;pushup(x);
    }
}
void makeroot(int x) {access(x);splay(x);pushr(x);}
void split(int x,int y) {makeroot(x);access(y);splay(y);}
void link(int x,int y) {split(x,y);fa[x] = y;s2[y] ^= s1[x];}
void cut(int x,int y) {split(x,y);ch[y][0] = fa[x] = 0;pushup(y);}
void ins(int x,ull w) {makeroot(x);val[x] ^= w;s1[x] ^= w;}
int main() {
    int top = 0,xzc;ull sum = 0;
    xzc = read();n = read();m = read();
    for(int i = 1;i < n;i++) {
        int a = read(),b = read();link(a,b);
    }
    while(m--) {
        int opt = read();
        if(opt == 1) {int x = read(),y = read(),u = read(),v = read();cut(x,y);link(u,v);}
        if(opt == 2) {
            top++;L[top] = read();R[top] = read();rnd[top] = 1ull * rand() * rand() * rand() * rand() * rand();
            ins(L[top],rnd[top]);ins(R[top],rnd[top]);sum ^= rnd[top];
        }
        if(opt == 3) {
            int id = read();ins(L[id],rnd[id]);ins(R[id],rnd[id]);sum ^= rnd[id];
        }
        if(opt == 4) {
            int x = read(),y = read();split(x,y);
            if(s1[x] ^ sum) puts("NO");else puts("YES");
        }
    }
}
全部评论

相关推荐

我即大橘:耐泡王
点赞 评论 收藏
分享
4 收藏 评论
分享
牛客网
牛客企业服务