BZOJ2002 [HNOI2010]弹飞绵羊
【问题描述】
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿 着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置, 则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何 时候弹力系数均为正整数。
【输入格式】
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m, 接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成 k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
【输出格式】
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
【输入样例】
4
1 2 1 1
3
1 1
2 1 1
1 1
【输出样例】
2
3
正解:LCT
解题报告:直接用动态树维护,然后在splay里面维护一个子树的大小size就可以了。
1 #include <iostream> 2 #include <iomanip> 3 #include <string> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstring> 7 #include <cstdlib> 8 #include <cstdio> 9 #define RG register 10 const int N = 300000; 11 12 using namespace std; 13 14 int gi(){ 15 char ch=getchar();int x=0; 16 while(ch<'0' || ch>'9') ch=getchar(); 17 while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); 18 return x; 19 } 20 21 int n,m,f[N],fa[N],rev[N],c[N][2],st[N],nx[N],siz[N]; 22 23 int isroot(int x){ 24 return c[fa[x]][0]!=x && c[fa[x]][1]!=x; 25 } 26 27 void pushdown(int x){ 28 if (rev[x]==0) return; 29 RG int l=c[x][0],r=c[x][1]; 30 rev[x]^=1,rev[l]^=1,rev[r]^=1; 31 swap(c[x][0],c[x][1]); 32 return; 33 } 34 35 void pushsum(int x){ 36 siz[x]=siz[c[x][0]]+siz[c[x][1]]+1; 37 return; 38 } 39 40 void rotate(int x){ 41 RG int l,r,y=fa[x],z=fa[y]; 42 if (c[y][0]==x) l=0; 43 else l=1;r=l^1; 44 if (!isroot(y)) 45 if (c[z][0]==y) c[z][0]=x; 46 else c[z][1]=x; 47 fa[c[x][r]]=y,fa[y]=x,fa[x]=z; 48 c[y][l]=c[x][r],c[x][r]=y; 49 pushsum(y),pushsum(x); 50 return; 51 } 52 53 void splay(int x){ 54 RG int tot=0; 55 st[++tot]=x; 56 for (RG int i=x; !isroot(i); i=fa[i]) st[++tot]=fa[i]; 57 for (RG int i=tot; i; --i) pushdown(st[i]); 58 while(!isroot(x)){ 59 RG int y=fa[x],z=fa[y]; 60 if (!isroot(y)) 61 if (c[y][0]==x ^ c[z][0]==y) rotate(x); 62 else rotate(y); 63 rotate(x); 64 } 65 return; 66 } 67 68 void access(int x){ 69 int t=0; 70 while(x){ 71 splay(x); 72 c[x][1]=t; 73 t=x,x=fa[x]; 74 } 75 return; 76 } 77 78 void rever(int x){ 79 access(x),splay(x),rev[x]^=1; 80 return; 81 } 82 83 void cut(int x,int y){ 84 rever(x),access(y),splay(y); 85 c[y][0]=fa[x]=0; 86 return; 87 } 88 89 void link(int x,int y){ 90 rever(x); 91 fa[x]=y; 92 return; 93 } 94 95 int main(){ 96 n=gi();RG int s,l,r;siz[n+1]=1; 97 for (RG int i=1; i<=n; ++i) f[i]=gi(),siz[i]=1;m=gi(); 98 for (RG int i=1; i<=n; ++i) nx[i]=i+f[i]<=n?i+f[i]:n+1; 99 for (RG int i=1; i<=n; i++) fa[i]=nx[i]; 100 for (RG int i=1; i<=m; i++){ 101 s=gi(),l=gi()+1; 102 if (s==1){ 103 rever(n+1); 104 access(l); 105 splay(l); 106 printf("%d\n",siz[c[l][0]]); 107 } 108 else{ 109 cut(l,nx[l]); 110 r=gi(),nx[l]=l+r<=n?l+r:n+1; 111 link(l,nx[l]); 112 } 113 } 114 return 0; 115 }