bzoj2002: [Hnoi2010]Bounce 弹飞绵羊
块状链表。维护一个点f[i]次能到达下一个块,和到哪个位置。
#include<cstdio> #include<cmath> using namespace std; const int maxn = 400000 + 100; int k[maxn],jump[maxn],st[maxn],belong[maxn],f[maxn]; int n,m,tot=1; void build() { scanf("%d",&n); int len = (int)sqrt(n); for(int i=0,j=0;i<n;i++) { j++; if(j==len+1) { j=1; tot++; st[tot]=i; } belong[i]=tot; scanf("%d",&k[i]); } belong[n]=tot+1; for(int i=n-1;i>=0;i--) { if(i+k[i]>=st[belong[i]+1]) { f[i]=1; jump[i]=i+k[i]; } else { f[i]=f[i+k[i]]+1; jump[i]=jump[i+k[i]]; } } } void change(int x,int c) { k[x]=c; for(int i=x;i>=st[belong[x]];i--) { if(i+k[i]>=st[belong[i]+1]) { f[i]=1; jump[i]=i+k[i]; } else { f[i]=f[i+k[i]]+1; jump[i]=jump[i+k[i]]; } } } void solve() { scanf("%d",&m); for(int i=1,t,x,c;i<=m;i++) { scanf("%d%d",&t,&x); if(t==1) { int res=0; while(x<n) { res+=f[x]; x=jump[x]; } printf("%d\n",res); } else { scanf("%d",&c); k[x]=c; for(int i=x;i>=st[belong[x]];i--) { if(i+k[i]>=st[belong[i]+1]) { f[i]=1; jump[i]=i+k[i]; } else { f[i]=f[i+k[i]]+1; jump[i]=jump[i+k[i]]; } } } } } int main() { build(); solve(); return 0; }