就是个板子。
又短又爽我爱了。
namespace LCT
{
int ch[2][MAXM],fa[MAXM],rev[MAXM];
int sta[MAXM],tp;
bool son(int x){return x==ch[1][fa[x]];}
bool isroot(int x){return ch[0][fa[x]]!=x&&ch[1][fa[x]]!=x;}
void reverse(int x){if(x)swap(ch[0][x],ch[1][x]),rev[x]^=1;}
void pushdown(int x){if(rev[x])reverse(ch[0][x]),reverse(ch[1][x]),rev[x]=0;}
void updata(int x){//暂未操作}
void rotate(int x)
{
int y=fa[x],z=fa[y],c=son(x);
ch[c][y]=ch[c^1][x];if(ch[c][y])fa[ch[c][y]]=y;
fa[x]=z;if(!isroot(y))ch[son(y)][z]=x;
ch[c^1][x]=y;fa[y]=x;updata(y);updata(x);
}
void splay(int x)
{
sta[tp=1]=x;
for(int i=x;!isroot(i);i=fa[i])sta[++tp]=fa[i];
while(tp)pushdown(sta[tp--]);
for(int y=fa[x];!isroot(x);rotate(x),y=fa[x])
if(!isroot(y))son(x)^son(y)?rotate(x):rotate(y);
}
void access(int x)
{
for(int y=0;x;y=x,x=fa[x])
splay(x),ch[1][x]=y,updata(y);
}
void markroot(int x){access(x);splay(x);reverse(x);}
int findroot(int x)
{
access(x);splay(x);
while(ch[0][x])pushdown(x),x=ch[0][x];
splay(x);return x;
}
void split(int x,int y){markroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);ch[0][y]=fa[x]=0;updata(y);}
void link(int x,int y){markroot(x);fa[x]=y;}
}