[HNOI2010] 弹飞绵羊
题目链接:戳我
比较模板的LCT了。。。。
如果是更改操作的话就是先断开它和原先往后弹到的那个边,之后再连上新边。
如果是查询操作就询问它到弹飞点的距离。
那么弹飞点如何处理呢?就是新开一个点(比如说n+1)当某个点如果会被弹飞的话就向它连一条边即可。
注意函数中x,y的先后关系是有影响的。
其他就没有什么了,就是LCT的普通操作啦。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 200010
using namespace std;
int n,m,tot,to,op,cur,p;
int s[MAXN];
struct Node{int ch[2],val,ff,rev,son;}t[MAXN];
inline int ls(int x){return t[x].ch[0];}
inline int rs(int x){return t[x].ch[1];}
inline void push_up(int x){t[x].son=t[ls(x)].son+t[rs(x)].son+1;}
inline bool isroot(int x){return (ls(t[x].ff)!=x)&&(rs(t[x].ff)!=x);}
inline void push_down(int x)
{
if(t[x].rev==0) return;
t[ls(x)].rev^=1,t[rs(x)].rev^=1;
swap(t[x].ch[0],t[x].ch[1]);
t[x].rev^=1;
}
inline void rotate(int x)
{
int y=t[x].ff;
int z=t[y].ff;
int k=t[y].ch[1]==x;
if(!isroot(y)) t[z].ch[t[z].ch[1]==y]=x; t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y; t[y].ff=x;
push_up(y),push_up(x);
}
inline void splay(int x)
{
s[tot=1]=x;
for(int i=x;!isroot(i);i=t[i].ff) s[++tot]=t[i].ff;
while(tot) push_down(s[tot--]);
while(!isroot(x))
{
int y=t[x].ff,z=t[y].ff;
if(!isroot(y))
((t[y].ch[0]==x)^(t[z].ch[0]==y))?rotate(x):rotate(y);
rotate(x);
}
}
inline void access(int x)
{
for(int y=0;x;y=x,x=t[x].ff)
splay(x),t[x].ch[1]=y,push_up(x);
}
inline void makeroot(int x){access(x);splay(x);t[x].rev^=1;}
inline void split(int x,int y){makeroot(x);access(y);splay(y);}
inline void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;}
inline void link(int x,int y){makeroot(x);t[x].ff=y;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
to=n+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i].val);
t[i].son=1;
if(t[i].val+i>n) link(to,i);
else link(i+t[i].val,i);
}
t[n+1].son=1;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&op,&cur);cur++;
if(op==1)
{
split(to,cur);
printf("%d\n",t[cur].son-1);
}
else
{
scanf("%d",&p);
if(t[cur].val+cur>n) cut(to,cur);
else cut(t[cur].val+cur,cur);
t[cur].val=p;
link(cur,min(t[cur].val+cur,to));
}
}
}