版权声明:转载请注明原出处啦(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/82926546
两个月没有写LCT了,这次写一遍复习一下.
题目:bzoj2002.
题目大意:给定一棵树,支持两种操作:
1.格式1 j,表示查询j的深度.
2.格式2 j k,表示修改j的父亲为j+k.
这道题是一个十分容易的LCT套路题(然而我还是看了好久题解才懂).
这棵树虽然是个有根树,要求一个节点的深度,就是求它到根的距离+1.
所以我们发现,我们可以建一个虚点n+1作为所有树的根.接下来我们把虚点移到根的地方,求一个点到这个根的距离.
这时候我们把这个点access一下,然后发现它现在是深度最大的点,且它到这个虚点的这条链被独立了出来,此时这条链的大小-1就是距离.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=200000;
int n,m,tmp[N+9],ttmp,nxt[N+9];
struct tree{
int size,rev,s[2],fa;
}tr[N+9];
bool isroot(int x){
return tr[tr[x].fa].s[0]^x&&tr[tr[x].fa].s[1]^x;
}
void pushup(int x){
tr[x].size=tr[tr[x].s[0]].size+tr[tr[x].s[1]].size+1;
}
void update_rev(int x){
tr[x].rev^=1;
swap(tr[x].s[0],tr[x].s[1]);
}
void pushdown(int x){
if (!tr[x].rev) return;
tr[x].rev=0;
update_rev(tr[x].s[0]);update_rev(tr[x].s[1]);
}
void rtt(int x){
int y=tr[x].fa,z=tr[y].fa,k=tr[y].s[1]==x;
if (!isroot(y)) tr[z].s[tr[z].s[1]==y]=x;tr[x].fa=z;
tr[y].s[k]=tr[x].s[k^1];if (tr[x].s[k^1]) tr[tr[x].s[k^1]].fa=y;
tr[x].s[k^1]=y;tr[y].fa=x;
pushup(y);pushup(x);
}
void splay(int x){
int y,z;
tmp[ttmp=1]=x;
for (int i=x;!isroot(i);i=tr[i].fa) tmp[++ttmp]=tr[i].fa;
for (;ttmp;ttmp--) pushdown(tmp[ttmp]);
while (!isroot(x)){
y=tr[x].fa,z=tr[y].fa;
if (!isroot(y)) tr[y].s[1]==x^tr[z].s[1]==y?rtt(x):rtt(y);
rtt(x);
}
pushup(x);
}
void access(int x){
for (int t=0;x;t=x,x=tr[x].fa){
splay(x);
tr[x].s[1]=t;
pushup(x);
}
}
void makeroot(int x){
access(x);splay(x);
update_rev(x);
}
int root(int x){
access(x);splay(x);
while (tr[x].s[0]) x=tr[x].s[0];
return x;
}
void split(int x,int y){
makeroot(x);
access(y);splay(y);
}
void link(int x,int y){
if (root(x)==root(y)) return;
makeroot(x);
tr[x].fa=y;
}
void cut(int x,int y){
if (root(x)^root(y)) return;
split(x,y);
if (tr[y].s[0]^x||tr[x].s[1]||tr[y].s[1]) return;
tr[x].fa=tr[y].s[0]=0;
}
int query(int x){
split(x,n+1);
return tr[n+1].size-1;
}
Abigail into(){
scanf("%d",&n);
int y;
for (int i=1;i<=n;i++){
scanf("%d",&y);
tr[i].size=1;
if (i+y>n) link(i,n+1),nxt[i]=n+1;
else link(i,i+y),nxt[i]=i+y;
}
tr[n+1].size=1;
}
Abigail work(){
}
Abigail outo(){
}
Abigail getans(){
int opt,x,y,m;
scanf("%d",&m);
for (int i=1;i<=m;i++){
scanf("%d",&opt);
if (opt==1){
scanf("%d",&x);++x;
printf("%d\n",query(x));
}else{
scanf("%d%d",&x,&y);++x;
cut(x,nxt[x]);
if (x+y>n) link(x,n+1),nxt[x]=n+1;
else link(x,x+y),nxt[x]=x+y;
}
}
}
int main(){
into();
work();
outo();
getans();
return 0;
}