传送门biu~
最终的图一定是一棵树,算一个点被弹飞需要几次只需要计算一下这个点到根的路径上有多少点就可以了,LCT。
分块做法【点这里】
#include<bits/stdc++.h>
using namespace std;
struct Node{
Node *ch[2],*fa;
int siz;
Node();
inline int dir(){
if(fa->ch[0]==this) return 0;
if(fa->ch[1]==this) return 1;
return -1;
}
inline void maintain();
}*null=new Node,tree[200005];
Node :: Node(){
ch[0]=ch[1]=fa=null;
siz=1;
}
inline void Node :: maintain(){
if(this==null) return;
siz=ch[0]->siz+ch[1]->siz+1;
}
inline void Rotate(Node *o,int d){
Node *p=o->ch[d^1];
o->ch[d^1]=p->ch[d];p->ch[d]->fa=o;
p->ch[d]=o;
o->maintain();p->maintain();
if(~o->dir()) o->fa->ch[o->dir()]=p;
p->fa=o->fa;o->fa=p;
}
inline void Splay(Node *o){
while(~o->dir()){
if(o->dir()==o->fa->dir()) Rotate(o->fa->fa,o->dir()^1);
Rotate(o->fa,o->dir()^1);
}
}
inline void Access(Node *o){
Node *p=null;
while(o!=null){
Splay(o);
o->ch[1]=p; o->maintain();
p=o;
o=o->fa;
}
}
inline void Link(Node *x,Node *y){
Access(x);
Splay(x);
x->ch[0]->fa=null;
x->ch[0]=null;
x->fa=y;
x->maintain();
}
int main(){
null->siz=0;
Node *root;
int n,m;
scanf("%d",&n);
for(int i=1;i<=n;++i){
int x;
scanf("%d",&x);
if(i+x<=n) tree[i].fa=&tree[i+x];
}
scanf("%d",&m);
while(m--){
int opt;
scanf("%d",&opt);
if(opt==1){
int x;
scanf("%d",&x);++x;
Access(&tree[x]);
Splay(&tree[x]);
printf("%d\n",tree[x].siz);
}
else{
int x,y;
scanf("%d%d",&x,&y);++x;
if(x+y<=n) root=&tree[x+y];
else root=null;
Link(&tree[x],root);
}
}
return 0;
}