Link Cut Tree 学习笔记

Link Cut Tree 学习笔记

标签(空格分隔): LCT


说在前边

最近补 CF 碰见一道 LCT ,就打算学习一下这个东西。。。顺便复习一下 splay。

具体算法及实现

参考了FlashHuCandy?

题目:给定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。

做法:模板

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
typedef long long ll;
const int N = 300010;
const int inf = 0x3f3f3f3f;
template<class T> inline void read(T &x) {
    x = 0; char c = getchar(); T f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {x = x * 10 + c - '0'; c = getchar();}
    x *= f;
}
using namespace std;
class LCT {
private :
    struct Node {
        int ch[2], fa, rev, sum, w;
    } T[N];
    int st[N];
    #define lc T[p].ch[0]
    #define rc T[p].ch[1]
    #define pa T[p].fa
    inline int LR(int p) { return T[pa].ch[1] == p; }
    inline int isR(int p) { return T[pa].ch[0] != p && T[pa].ch[1] != p; }
    inline void PushUp(int p) { T[p].sum = T[lc].sum ^ T[rc].sum ^ T[p].w; }
    inline void Pushr(int p) { T[p].rev ^= 1; swap(lc, rc); }
    inline void PushDown(int p) {
        if(T[p].rev) {
            if(lc) Pushr(lc);
            if(rc) Pushr(rc);
            T[p].rev = 0;
        }
    }
    inline void rotate(int p) {
        int f=T[p].fa, g=T[f].fa, c=LR(p);
        if(!isR(f)) T[g].ch[LR(f)]=p; T[p].fa=g;
        T[f].ch[c] = T[p].ch[c^1]; T[T[f].ch[c]].fa=f;
        T[p].ch[c^1] = f; T[f].fa=p;
        PushUp(f); PushUp(p);
    }
    inline void splay(int p) {
        int y=p,z=0; st[++z]=y;
        while(!isR(y)) st[++z]=y=T[y].fa;
        while(z) PushDown(st[z--]);
        while(!isR(p)) {
            y=T[p].fa;z=T[y].fa;
            if(!isR(y)) rotate((T[y].ch[0]==p)^(T[z].ch[0]==y)?p:y);
            rotate(p);
        }
        PushUp(p);
    }
    inline void access(int p) {
        for(int y = 0; p; p = T[y = p].fa)
            splay(p), rc = y, PushUp(p);
    }
    inline void makeR(int p) {
        access(p); splay(p); Pushr(p);
    }
    int findR(int p) {
        access(p); splay(p);
        while(lc) PushDown(p), p = lc;
        splay(p);
        return p;
    }
public :
    inline void split(int x, int y) {
        makeR(x); access(y); splay(y);
    }
    inline void Link(int x, int y) {
        makeR(x);
        if(findR(y)!=x)T[x].fa=y;
    }
    inline void Cut(int x, int y) {
        makeR(x);
        if(findR(y) == x && T[y].fa == x && !T[y].ch[0]) {
            T[y].fa = T[x].ch[1] = 0; PushUp(x);
        }
    }
    inline int getSum(int p) { return T[p].sum; }
    inline void setW(int p, int v) { splay(p);T[p].w = v;PushUp(p); }
} tree;
int n, q, opt, u, v;
int main() {
    read(n), read(q);
    for(int i = 1; i <= n; ++i) read(v), tree.setW(i, v);
    while(q--) {
        read(opt), read(u), read(v);
        if(opt == 0) tree.split(u, v), printf("%d\n",tree.getSum(v));
        else if(opt == 1) tree.Link(u, v);
        else if(opt == 2) tree.Cut(u, v);
        else if(opt == 3) tree.setW(u, v);
    }
}

猜你喜欢

转载自www.cnblogs.com/RRRR-wys/p/10527816.html