LCT模板
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lch ch[root][0]
#define rch ch[root][1]
#define fat fa[root]
using namespace std;
const int Maxn=1100000;
int size[Maxn],fa[Maxn],ch[Maxn][2],flag[Maxn],st[Maxn],top;
inline void update(int root) {
size[root]=size[lch]+size[rch]+1;
}
inline int isroot(int root) {
return ch[fat][0]==root||ch[fat][1]==root;
}
inline int son(int root) {
return ch[fat][1]==root;
}
inline void pushr(int root) {
flag[root]^=1;
swap(lch,rch);
}
inline void pushdown(int root) {
if(flag[root]) {
flag[root]^=1;
pushr(lch);
pushr(rch);
}
}
int min(int root) {
pushdown(root);
if(lch) return min(lch);
return root;
}
void rotate(int root) {
int y=fat,z=fa[y];
if(isroot(z)) ch[z][son(y)]=root;
int d=son(root),x=ch[root][d^1];
ch[y][d]=x;
fa[y]=root;
fa[root]=z;
if(x) fa[x]=y;
ch[root][d^1]=y;
update(y);
}
void splay(int root) {
top=0;
int temp=root;
while(isroot(temp)) st[++top]=temp,temp=fa[temp];
for(int i=top;i>=1;i--) pushdown(st[i]);
while(isroot(root)) {
if(isroot(fat)) rotate(son(root)==son(fat)?fat:root);
rotate(root);
}update(root);
}
void access(int root) {
for(int i=0;root;root=fa[i=root])
splay(root),rch=i,update(root);
}
void makeroot(int root) {
access(root);
splay(root);
pushr(root);
}
int findroot(int root) {
access(root);
splay(root);
int temp=min(root);
return temp;
}
void split(int root,int y) {
makeroot(root);
access(y);
splay(y);
}
void link(int root,int y) {
makeroot(root);
if(findroot(y)!=root) fat=y;
}
void cut(int root,int y) {
makeroot(root);
if(findroot(y)==root&&fat==y&&rch==0) fat=ch[y][0]=0,update(y);
}
int main() {
return 0;
}
lct通过维护若干棵splay来维护树上的若干条链,进而对链进行查询和修改。在不同的链之间,以单向的边链接,即只记父亲,不记儿子。
son:询问该节点是其父节点的哪个儿子。
isroot:若该点是对应了一条链的splay的根,则返回1,否则返回0。
pushr:子树翻转。
splay:将当前节点旋转至对应的一条链的splay的根处。
min:返回子树中最左一点。
access:将当前节点与根节点连成一条链。
makeroot:将当前节点变为根。方法为先access当前点后当前点与根节点处于一颗splay中,然后将当前点旋到根,翻转整颗树,则当前点变为根节点。
split:提取出root到y的链。
link:在root与y之间连边。
cut:将root与y之间的边断开。