[BZOJ 2002][Hnoi 2010]Bounce 弹飞绵羊
有两种写法
一.可以用块状链表水过
代码:
1 #include<cmath> 2 #include<cstdio> 3 #define N 200100 4 using namespace std; 5 6 int n,m,q,cnt,a,b,c; 7 int s[N],f[N],g[N],num[N]; 8 9 void build() 10 { 11 m=(int) sqrt(n); 12 cnt=(n-1)/m; 13 for (int i=0;i<n;i++) num[i]=i/m; 14 num[n]=cnt+1; 15 for (int i=n-1;i>=0;i--) 16 { 17 if (s[i]+i>=n){f[i]=1;g[i]=n;} 18 else if (num[i]==num[s[i]+i]) {f[i]=f[s[i]+i]+1;g[i]=g[s[i]+i];} 19 else {f[i]=1;g[i]=s[i]+i;} 20 } 21 } 22 23 void Query(int a) 24 { 25 int ans=0; 26 while (num[a]<=cnt) 27 { 28 ans+=f[a]; 29 a=g[a]; 30 } 31 printf("%d\n",ans); 32 } 33 34 void Change(int a,int b) 35 { 36 s[a]=b; 37 for (int i=a;i>=0&&num[i]==num[a];i--) 38 { 39 if (s[i]+i>=n){f[i]=1;g[i]=n;} 40 else if (num[i]==num[s[i]+i]) {f[i]=f[s[i]+i]+1;g[i]=g[s[i]+i];} 41 else {f[i]=1;g[i]=s[i]+i;} 42 } 43 } 44 45 int main() 46 { 47 scanf("%d",&n); 48 for (int i=0;i<n;i++) scanf("%d",s+i); 49 build(); 50 scanf("%d",&q); 51 for (int i=1;i<=q;i++) 52 { 53 scanf("%d%d",&a,&b); 54 if (a==1) Query(b); 55 else {scanf("%d",&c);Change(b,c);} 56 } 57 return 0; 58 }
二.lct可以完美解决,这个题算是lct模板题吧
1 #include<cstdio> 2 #define N 200100 3 4 int n,m,a,b,c,null; 5 int f[N],pos[N],son[N][2],sum[N]; 6 7 void Change(int a,int b,int c) 8 { 9 if (b) f[b]=a; 10 if (b) pos[b]=c; 11 if (c<2) son[a][c]=b; 12 } 13 14 void update(int x){sum[x]=sum[son[x][0]]+sum[son[x][1]]+1;} 15 16 void ziag(int x) 17 { 18 int y=f[x],P=pos[x],S=son[x][P^1]; 19 Change(f[y],x,pos[y]); 20 Change(y,S,P); 21 Change(x,y,P^1); 22 update(y); 23 update(x); 24 } 25 26 void Splay(int x) 27 { 28 int y,t1,t2; 29 while (1) 30 { 31 y=f[x]; 32 if (pos[x]==2) return; 33 t1=pos[x]; 34 ziag(x); 35 if (pos[x]==2) return; 36 t2=pos[x]; 37 ziag(x); 38 if (t1==t2) ziag(y); 39 } 40 } 41 42 void Access(int v) 43 { 44 int u=v; 45 v=0; 46 while (u) 47 { 48 Splay(u); 49 pos[son[u][1]]=2; 50 son[u][1]=v; 51 update(u); 52 if (v){f[v]=u;pos[v]=1;} 53 v=u; 54 u=f[u]; 55 } 56 } 57 58 void Cut(int v) 59 { 60 Splay(v); 61 f[son[v][0]]=f[v]; 62 pos[son[v][0]]=2; 63 son[v][0]=0; 64 update(v); 65 } 66 67 int main() 68 { 69 scanf("%d",&n); 70 pos[0]=2; 71 for (int i=1;i<=n;i++) 72 { 73 scanf("%d",&a); 74 if (i+a<=n) f[i]=i+a; 75 else f[i]=0; 76 pos[i]=2; 77 sum[i]=1; 78 } 79 scanf("%d",&m); 80 for (int i=0;i<m;i++) 81 { 82 scanf("%d%d",&a,&b); 83 b++; 84 if (a==1) 85 { 86 Access(b); 87 Splay(b); 88 printf("%d\n",sum[b]); 89 } 90 else 91 { 92 scanf("%d",&c); 93 Cut(b); 94 if (b+c<=n) f[b]=b+c; 95 else f[b]=0; 96 } 97 } 98 return 0; 99 }