HDU - 5967(LCT)
LCT动态维护基环内向树
将树边直接加入,对于根节点记录一个\(mark\)值存多出来一条边的信息
查询时找到当前树的根,然后根据\(mark\)值判断
#include<cstdio>
#include<cctype>
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
char IO;
int rd(){
int s=0,f=0;
while(!isdigit(IO=getchar())) if(IO=='-') f=1;
do s=(s<<1)+(s<<3)+(IO^'0');
while(isdigit(IO=getchar()));
return f?-s:s;
}
const int N=2e5+10;
int n,m;
int fa[N],son[N][2];
inline int dir(int x){ return son[fa[x]][1]==x; }
inline int isroot(int x){ return !fa[x]||(son[fa[x]][0]!=x&&son[fa[x]][1]!=x); }
void rotate(int u){
int f=fa[u],ff=fa[f],d=dir(u);
fa[u]=ff; if(!isroot(f)) son[ff][dir(f)]=u;
son[f][d]=son[u][!d]; if(son[u][!d]) fa[son[u][!d]]=f;
fa[f]=u; son[u][!d]=f;
}
void Splay(int x) {
while(!isroot(x)) {
int f=fa[x];
if(!isroot(f)) {
if(dir(x)^dir(f)) rotate(x);
else rotate(f);
}
rotate(x);
}
}
void Access(int x){ for(int t=0;x;t=x,x=fa[x]) Splay(x),son[x][1]=t; }
int GetRoot(int x) {
Access(x),Splay(x);
while(son[x][0]) x=son[x][0];
Splay(x);
return x;
}
int mk[N];
void Link(int x,int to) {
if(!to) return;
if(GetRoot(x)==GetRoot(to)) {
mk[x]=to;
return;
} else mk[x]=0;
Splay(x);
fa[x]=to;
}
void Cut(int x) {
int rt=GetRoot(x);
if(x==rt) {
mk[x]=0;
return;
}
Access(x);
Splay(x);
fa[son[x][0]]=0;
son[x][0]=0;
if(mk[rt]) Link(rt,mk[rt]);
}
int main(){
n=rd(),m=rd();
rep(i,1,n) Link(i,rd());
rep(i,1,m) {
int opt=rd();
if(opt==1) {
int x=rd();
Cut(x);
Link(x,rd());
} else {
int rt=GetRoot(rd());
if(mk[rt]) puts("-1");
else printf("%d\n",rt);
}
}
}