LCT板子题...
看到题目中的操作很显然是从$i$向$i+k_{i}$连一条边,每次修改就是删除原来的边再加入一条新的边嘛
然后考虑查询:对于被弹飞的部分,我们统一新建一个节点$n+1$,把所有越过边界的部分指向这个节点即可
然后在查询的时候只需要拎出查询节点到$n+1$节点的树链,统计其大小即可
注意节点编号读入时加一
贴代码:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> using namespace std; int siz[200005]; int ch[200005][2]; int fl[200005],f[200005]; int to[200005]; int n,m; void update(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } bool be_root(int x) { if(ch[f[x]][0]==x||ch[f[x]][1]==x)return 0; return 1; } void pushdown(int x) { if(fl[x]) { swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); swap(ch[ch[x][1]][0],ch[ch[x][1]][1]); fl[ch[x][0]]^=1,fl[ch[x][1]]^=1; fl[x]=0; } } void repush(int x) { if(!be_root(x))repush(f[x]); pushdown(x); } void rotate(int x) { int y=f[x],z=f[y],k=(ch[y][1]==x); if(!be_root(y))ch[z][ch[z][1]==y]=x; f[x]=z; ch[y][k]=ch[x][!k],f[ch[x][!k]]=y; ch[x][!k]=y,f[y]=x; update(y),update(x); } void splay(int x) { repush(x); while(!be_root(x)) { int y=f[x],z=f[y]; if(!be_root(y)) { if((ch[y][1]==x)^(ch[z][1]==y))rotate(x); else rotate(y); } rotate(x); } update(x); } void access(int x) { int y=0; while(x) { splay(x); ch[x][1]=y; update(x); y=x,x=f[x]; } } int get_root(int x) { access(x),splay(x); while(ch[x][0])pushdown(x),x=ch[x][0]; return x; } void make_root(int x) { access(x),splay(x); swap(ch[x][0],ch[x][1]),fl[x]^=1; } void link(int x,int y) { make_root(x); if(get_root(y)!=x)f[x]=y; } void cut(int x,int y) { make_root(y); if(get_root(x)==y&&f[y]==x&&!ch[y][1])ch[x][0]=f[y]=0,update(x); } inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(); for(int i=1;i<=n;i++)to[i]=read(),link(i,min(i+to[i],n+1)); m=read(); while(m--) { int typ=read(); if(typ==1) { int x=read()+1; make_root(x),access(n+1),splay(n+1); printf("%d ",siz[n+1]-1); }else { int x=read()+1,y=read(); cut(x,min(x+to[x],n+1)); to[x]=y; link(x,min(x+to[x],n+1)); } } return 0; }