某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一块儿玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上\(n\)个装置,每一个装置设定初始弹力系数\(k_i\),当绵羊达到第\(i\)个装置时,它会往前弹\(k_i\)步,达到第\(i+k_i\)个装置,若不存在第\(i+k_i\)个装置,则绵羊被弹飞。绵羊想知道当它从第\(i\)个装置起步时,被弹几回后会被弹飞。为了使得游戏更有趣,Lostmonkey能够修改某个弹力装置的弹力系数,任什么时候候弹力系数均为正整数。ios
第一行包含一个整数\(n\),表示地上有\(n\)个装置,装置的编号从\(0\)到\(n-1\)。
接下来一行有\(n\)个正整数,依次为那\(n\)个装置的初始弹力系数。
第三行有一个正整数\(m\)。
接下来\(m\)行每行至少有两个数\(i,j\),若\(i=1\),你要输出从\(j\)出发被弹几回后被弹飞,若\(i=2\)则还会再输入一个正整数\(k\),表示第\(j\)个弹力装置的系数被修改为\(k\)。spa
对于每一个\(i=1\)的状况,你都要输出一个须要的步数,占一行。code
4
1 2 1 1
3
1 1
2 1 1
1 1
排序
2
3
游戏
对于20%的数据\(n,m\le 10000\);
对于100%的数据\(n\le 200000,m\le 100000\);ip
根为\(\textbf{n+1}\)get
以样例作例子:
input
为蛤哈?
因为splay是按深度关键字排序,因此根的左子树的大小就是要被弹几回了呀。io
把原来的边删了在连新的不就完了吗……class
#include<iostream> #include<cstdio> using namespace std; int ch[200002][2],fa[200002],siz[200002],num[200002],lazr[200002],cnt,n,q; inline unsigned rd(){ unsigned re=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){ re=re*10+ch-'0'; ch=getchar(); } return re; } inline bool isroot(int bt){return ch[fa[bt]][0]!=bt&&ch[fa[bt]][1]!=bt;} inline int drct(int bt){return ch[fa[bt]][1]==bt;} inline void pushup(int bt){siz[bt]=siz[ch[bt][0]]+siz[ch[bt][1]]+1;} inline void reverse(int bt){swap(ch[bt][0],ch[bt][1]);lazr[bt]^=1;} inline void pd(int bt){ if(lazr[bt]){ if(ch[bt][0])reverse(ch[bt][0]); if(ch[bt][1])reverse(ch[bt][1]); lazr[bt]=0; } } inline void pushdown(int u){ if(!isroot(u))pushdown(fa[u]); pd(u); } inline void rotate(int u){ int f=fa[u],g=fa[f],c=drct(u); if(!isroot(f))ch[g][drct(f)]=u; fa[u]=g; ch[f][c]=ch[u][c^1]; if(ch[f][c])fa[ch[f][c]]=f; ch[u][c^1]=f; fa[f]=u; pushup(f); pushup(u); } void splay(int u){ pushdown(u); while(!isroot(u)){ if(!isroot(fa[u]))rotate(drct(fa[u])==drct(u)?fa[u]:u); rotate(u); } } void access(int u){ for(int v=0;u;v=u,u=fa[u]){ splay(u); ch[u][1]=v; pushup(u); } } void makeroot(int u){ access(u); splay(u); reverse(u); } void link(int a,int b){ makeroot(a); fa[a]=b; } void cut(int a,int b){ makeroot(a); access(b); splay(b); ch[b][0]=0; fa[a]=0; pushup(b); } int main(){ n=rd(); for(int i=1;i<=n;i++){ num[i]=rd(); siz[i]=1; } for(int i=1;i<=n;i++){ if(i+num[i]<=n)fa[i]=i+num[i]; else fa[i]=n+1; } q=rd(); for(int i=1;i<=q;i++){ int opt=rd(),x=rd()+1; if(opt==1){ makeroot(n+1); access(x); splay(x); printf("%d\n",siz[ch[x][0]]); }else{ int y=rd(); if(x+num[x]<=n)cut(x,x+num[x]); else cut(x,n+1); num[x]=y; if(x+num[x]<=n)link(x,x+num[x]); else link(x,n+1); } } }