BZOJ3282: Tree Luogu【模板】Link Cut Tree (动态树) LCT

版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/80108314

Description
给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。
0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。
1:后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接。
2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
3:后接两个整数(x,y),代表将点x上的权值变成y。


Sample Input
3 3
1
2
3
1 1 2
0 1 2
0 1 1


Sample Output
3
1


这道题拿来练Link Cut Tree模版。。。
但,被Luogu的小数据Hank掉了,因为不保证(x,y)存在,比如这样一组数据:
5 6 1 2 3 4 5
1 1 2
1 2 3
1 3 4
1 4 5
2 1 5
0 1 5
好吧,那你就特判一下。


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int _max(int x, int y) {return x > y ? x : y;}

struct node {
    int f, s, d, lazy, son[2];
} t[310000];
int tp, temp[310000];
char ss[11];

void Lazy(int x) {
    if(!t[x].lazy) return ;
    t[x].lazy = 0;
    swap(t[x].son[0], t[x].son[1]);
    int lc = t[x].son[0], rc = t[x].son[1];
    if(lc) t[lc].lazy ^= 1;
    if(rc) t[rc].lazy ^= 1;
}

void update(int x) {
    int lc = t[x].son[0], rc = t[x].son[1];
    t[x].s = t[x].d ^ t[lc].s ^ t[rc].s;
}

void rotate(int x, int fx) {
    int f = t[x].f, ff = t[f].f;
    int r, R;

    r = t[x].son[fx], R = f;
    if(r) t[r].f = R;
    t[R].son[1 ^ fx] = r;

    r = x, R = ff;
    t[r].f = R;
    if(t[ff].son[0] == f) t[R].son[0] = r; else if(t[ff].son[1] == f) t[R].son[1] = r;

    r = f, R = x;
    t[r].f = R;
    t[R].son[fx] = r;

    update(f);
    update(x);
}

bool hh(int x) {
    int f = t[x].f;
    if(f == 0 || (t[f].son[0] != x && t[f].son[1] != x)) return 0;
    return 1;
}

void splay(int x) {
    int i = x; tp = 0;
    while(hh(i)) temp[++tp] = i, i = t[i].f;
    temp[++tp] = i;
    for(int i = tp; i >= 1; i--) Lazy(temp[i]);
    while(hh(x)) {
        int f = t[x].f, ff = t[f].f;
        if(!hh(f)) {
            if(t[f].son[0] == x) rotate(x, 1);
            else rotate(x, 0);
        }
        else if(t[ff].son[0] == f && t[f].son[0] == x) rotate(f, 1), rotate(x, 1);
        else if(t[ff].son[0] == f && t[f].son[1] == x) rotate(x, 0), rotate(x, 1);
        else if(t[ff].son[1] == f && t[f].son[1] == x) rotate(f, 0), rotate(x, 0);
        else if(t[ff].son[1] == f && t[f].son[0] == x) rotate(x, 1), rotate(x, 0);
    }
}

void Access(int x) {
    int y = 0;
    while(x) {
        splay(x);
        t[x].son[1] = y;
        if(y) t[y].f = x;
        update(x);
        y = x; x = t[x].f;
    }
}

void Makert(int x) {
    Access(x); splay(x);
    t[x].lazy ^= 1;
}

void Link(int x, int y) {
    Makert(x); t[x].f = y; Access(x);
}

void Cut(int x, int y) {
    Makert(x);
    Access(y); splay(y);
    if(t[y].son[0] != x || (t[y].son[0] == x && t[x].son[1])) return ;
    t[t[y].son[0]].f = 0; t[y].son[0] = 0;
    update(y);
}

int Findrt(int x) {
    Access(x); splay(x);
    while(t[x].son[0]) x = t[x].son[0];
    return x;
}

int finds(int x, int y) {
    Makert(x);
    Access(y); splay(y);
    return t[y].s;
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        int x; scanf("%d", &x);
        t[i].d = t[i].s = x;
    }
    for(int i = 1; i <= m; i++) {
        int opt; scanf("%d", &opt);
        int x, y; scanf("%d%d", &x, &y);
        if(opt == 0) printf("%d\n", finds(x, y));
        else if(opt == 1) Link(x, y);
        else if(opt == 2) {
            if(Findrt(x) == Findrt(y)) Cut(x, y);
        }
        else {
            Makert(x);
            t[x].d = y;
            update(x);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xgc_woker/article/details/80108314