Link Cut Tree 学习笔记
标签(空格分隔): LCT
说在前边
最近补 CF 碰见一道 LCT ,就打算学习一下这个东西。。。顺便复习一下 splay。
具体算法及实现
P3690 【模板】Link Cut Tree (动态树)
题目:给定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);
}
}