【bzoj2002】弹飞绵羊——分块
这道题是很简单的分块吧,统计每个块里要中转的次数(即st数组),最后输出即可。
如果修改某个弹力装置的弹力系数,那么要从这个装置开始往回走到这一块的最左端(即l[belong[b]]),修改相对应的st数组和pt数组,它前面的块和后面的块都不受影响(因为st统计的是走到这一步到走出这一个装置所属的块所需的步数)。
具体实现细节看代码:
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> const int maxn=200010; using namespace std; int n,m,block,cnt; int pt[maxn],st[maxn],k[maxn],belong[maxn]; int l[1005],r[1005]; void print(int w) { int t=0; do{ t+=st[w]; w=pt[w]; }while(w); printf("%d\n",t); } int main() { scanf("%d",&n); block=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&k[i]); if(n%block)cnt=n/block+1; else cnt=n/block;//cnt存的是块的块数 for(int i=1;i<=cnt;i++) { l[i]=(i-1)*block+1; r[i]=i*block; } for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1; for(int i=n;i>=1;i--) { if(i+k[i]>n)st[i]=1; else if(belong[i]==belong[i+k[i]]) st[i]=st[i+k[i]]+1,pt[i]=pt[i+k[i]]; else st[i]=1,pt[i]=i+k[i]; } scanf("%d",&m); for(int i=1;i<=m;i++) { int a,b,c; scanf("%d %d",&a,&b); b++; if(a==1)print(b); else{ scanf("%d",&c); k[b]=c; for(int j=b;j>=l[belong[b]];j--) { if(belong[j]==belong[j+k[j]]) st[j]=st[j+k[j]]+1,pt[j]=pt[j+k[j]]; else st[j]=1,pt[j]=j+k[j]; } } } return 0; }