UOJ #207. 共價大爺遊長沙(不用維護子樹的LCT)

傳送門

題目大意:自己看題目吧。。


思路

這題真是機巧。

爲每一條路徑隨機一個權值,記錄每條邊上的異或值。對於一條刪邊,將其權值異或到新的路徑上,用LCT維護。

判斷一條邊是否被所有路徑經過只用判斷異或和是否相等就行了。

中間要用map等小技巧,還是比較簡單的,不用維護任何東西。但是難想。第一次寫隨機數衝突了,srand(num)比較可行。還有就是每次詢問之前別忘了splay一下。

還有一種維護子樹異或和的做法,這裏就不講了。(這也是基礎的操作啊)

推薦去看kekxy的博客。


代碼

#include <bits/stdc++.h>
#define maxn 200010
#define M1 998244353
#define M2 1000000007
#define M3 1333333331

using namespace std;

int ID, cnt, n, m, ToT, VAL;
map <long long, int> M;
int X[maxn], Y[maxn], Z[maxn];

struct Tnode{
    Tnode *son[2], *fa;
    int parent, val, add;
    bool rev;
    int Get_d(){return fa->son[1] == this;}
    void Connect(Tnode *now, int d){(son[d] = now)->fa = this;}
    void Down(){
        if(rev){
            swap(son[0], son[1]);
            if(son[0])  son[0]->rev ^= 1;
            if(son[1])  son[1]->rev ^= 1;
            rev = false;
        }
        if(add){
            if(son[0])  son[0]->val ^= add, son[0]->add ^= add;
            if(son[1])  son[1]->val ^= add, son[1]->add ^= add;
            add = 0;
        }
    }
}tree[maxn], *Node[maxn];

Tnode *NewTnode(){
    tree[cnt].fa = tree[cnt].son[0] = tree[cnt].son[1] = NULL;
    tree[cnt].parent = tree[cnt].add = 0;
    tree[cnt].rev = false;
    return tree+cnt++;
}

void Zig(Tnode *now){
    Tnode *last = now->fa;
    int d = now->Get_d();
    if(now->son[!d])  last->Connect(now->son[!d], d);
    else  last->son[d] = NULL;
    if(last->fa)  last->fa->Connect(now, last->Get_d());
    else  now->fa = NULL;
    now->Connect(last, !d);
    now->parent = last->parent;
    last->parent = 0;
}

void Splay(Tnode *now){
    Tnode *last;
    while(now->fa){
        last = now->fa;
        if(last->fa)  last->fa->Down();
        last->Down();  now->Down();
        if(last->fa)  (now->Get_d() ^ last->Get_d()) ? Zig(now) : Zig(last);
        Zig(now);
    }
    if(!now->fa)  now->Down();
}

void Access(int x){

    Splay(Node[x]);
    if(Node[x]->son[1]){
        Node[x]->son[1]->fa = NULL;
        Node[x]->son[1]->parent = x;
        Node[x]->son[1] = NULL;
    }

    int y = Node[x]->parent;
    while(y){
        Splay(Node[y]);
        if(Node[y]->son[1]){
            Node[y]->son[1]->fa = NULL;
            Node[y]->son[1]->parent = y;
            Node[y]->son[1] = NULL;
        }
        Node[y]->Connect(Node[x], 1);
        Node[x]->parent = 0;

        x = y;
        y = Node[x]->parent;
    }
}

void Evert(int x){
    Access(x);
    Splay(Node[x]);
    Node[x]->rev ^= 1;
}

void Link(int x, int y){
    Evert(x);
    Node[x]->parent = y;
}

void Cut(int x, int y){
    Evert(x);
    Access(y);
    Splay(Node[x]);
    Node[x]->son[1]->fa = NULL;
    Node[x]->son[1] = NULL;
}

void Update(int x, int y, int val){
    Evert(x);
    Access(y);
    Splay(Node[x]);
    Node[x]->val ^= val;
    Node[x]->add ^= val;
}

int Query(int x, int y){
    int edge = M[1LL*x*(n-1)+y];
    Splay(Node[edge]);
    return Node[edge]->val;
}

int Get(){
    VAL = (1LL * VAL * M1 + M2) % M3;
    return VAL;
}

int main(){

    scanf("%d", &ID);

    scanf("%d%d", &n, &m);

    for(int i = 1; i <= n; i++)  Node[i] = NewTnode();

    int a, b;
    for(int i = 1; i < n; i++){
        Node[i+n] = NewTnode();
        scanf("%d%d", &a, &b);
        M[1LL*a*(n-1)+b] = M[1LL*b*(n-1)+a] = i + n;
        Link(a, i+n);
        Link(i+n, b);
    }

    int op, u, v;
    for(int i = 1; i <= m; i++){
        scanf("%d", &op);
        if(op == 1){
            scanf("%d%d%d%d", &a, &b, &u, &v);

            int edge = M[1LL*a*(n-1)+b];
            Splay(Node[edge]);
            int val = Node[edge]->val;
            Cut(a, edge);
            Cut(edge, b);

            Node[edge]->fa = Node[edge]->son[0] = Node[edge]->son[1] = NULL;
            Node[edge]->val = Node[edge]->parent = 0;
            Node[edge]->rev = false;

            Link(u, edge);
            Link(edge, v);
            M[1LL*u*(n-1)+v] = M[1LL*v*(n-1)+u] = edge;
            Update(a, b, val);
        }
        else if(op == 2){
            scanf("%d%d", &a, &b);
            int val = Get();
            ToT ^= val;
            Update(a, b, val);
            X[++X[0]] = a;  Y[X[0]] = b;  Z[X[0]] = val;        
        }
        else if(op == 3){
            scanf("%d", &a);
            ToT ^= Z[a];
            Update(X[a], Y[a], Z[a]);
        }
        else{
            scanf("%d%d", &a, &b);
            int res = Query(a, b);
            if(res == ToT)  puts("YES");
            else  puts("NO");
        }
    }

    return 0;
} 

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章