链接
http://acm.hdu.edu.cn/showproblem.php?pid=5967
题解
用LCT,不要
m
a
k
e
r
o
o
t
makeroot
makeroot
一棵树的根节点可能是真的根节点
(
a
[
r
o
o
t
]
=
0
)
(a[root]=0)
(a[root]=0),也可能这个根节点还指向树里的另一个节点(这种情况下
a
[
r
o
o
t
]
=
̸
0
a[root]=\not0
a[root]≠0)
更改指向的时候,先切断原来的边,切断边之后,可能会破坏一个环,这时就要让假的根节点指向它应该指向的节点
切完了之后,再连接
查询祖先的时候,先找到这颗树的根节点,然后看下根节点是不是真的根节点
(
a
[
r
o
o
t
]
=
0
)
(a[root]=0)
(a[root]=0),如果是就输出其编号;但如果是假的根节点
(
a
[
r
o
o
t
]
=
̸
0
)
(a[root]=\not 0)
(a[root]≠0),就输出
−
1
-1
−1
代码
#include <bits/stdc++.h>
#define maxn 200010
using namespace std;
struct LinkCutTree
{
int rev[maxn], f[maxn], ch[maxn][2], s[maxn];
int getwh(int x)
{if(f[x]==0)return -1;if(ch[f[x]][0]==x)return 0;if(ch[f[x]][1]==x)return 1;return -1;}
bool isroot(int x){return getwh(x)==-1;}
void maketag_rev(int x){if(x)rev[x]^=1;}
void join(int x, int y, int wh){if(x)f[x]=y;if(y)ch[y][wh]=x;}
void pushdown(int x)
{
if(rev[x])
{
swap(ch[x][0],ch[x][1]);
maketag_rev(ch[x][0]), maketag_rev(ch[x][1]);
rev[x]=0;
}
}
void rotate(int x)
{
int y=f[x], z=f[y];
int c=getwh(x);
if(!isroot(y))join(x,z,getwh(y));
else f[x]=f[y];
join(ch[x][!c],y,c);
join(y,x,!c);
}
void splay(int x)
{
int y, top(0);
for(y=x;!isroot(y);y=f[y])s[++top]=y;s[++top]=y;
for(;top;top--)pushdown(s[top]);
while(!isroot(x))
{
y=f[x];
if(isroot(y)){rotate(x);break;}
if(getwh(x)^getwh(y))rotate(x);
else rotate(y);
rotate(x);
}
}
void access(int x)
{
int t=0;
while(x)
{
splay(x);
ch[x][1]=t;
t=x;x=f[x];
}
}
void makeroot(int x){access(x);splay(x);maketag_rev(x);}
void link(int x, int y){makeroot(x);f[x]=y;}
void cut(int x, int y)
{
makeroot(x); access(y);
splay(y);
if(ch[y][0]==x and ch[x][1]==0)f[x]=ch[y][0]=0;
}
int findroot(int x)
{
access(x); splay(x);
while(ch[x][0])pushdown(x), x=ch[x][0];
splay(x);
return x;
}
}lct;
int read(int x=0)
{
int c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
int a[maxn], n, m;
int main()
{
int i, j;
n=read(), m=read();
for(i=1;i<=n;i++)
{
a[i]=read();
if(a[i]==0)continue;
if(lct.findroot(a[i])!=i)
{
lct.splay(i);
lct.f[i]=a[i];
}
}
while(m--)
{
int type(read());
if(type==1)
{
int x(read()), y(read());
auto rt=lct.findroot(x);
if(rt!=x)
{
lct.access(a[x]);
lct.f[x]=0;
if(lct.findroot(a[rt])!=rt)
{
lct.splay(rt);
lct.f[rt]=a[rt];
}
}
if(y and lct.findroot(y)!=x)
{
lct.splay(x);
lct.f[x]=y;
}
a[x]=y;
}
else
{
int x(read());
int num=lct.findroot(x);
if(a[num]==0)printf("%d\n",num);
else printf("-1\n");
}
}
return 0;
}