BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)
题目:中文题,略
思路:看了黄学长的博客,之前一直听大腿吹,今天写了弹飞绵羊,有趣,其实这个题是维护了两个东西,一个是我第i个位置的下一个位置在哪,如果在同一块我就直接连接到下一个下一块的位置,我只在一个块上走一次,这样我有sqrtn块,所以查询和修改都是sqrt(n)
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; typedef long long LL; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=2e5+7; int n,m,block,cnt; int to[maxn],st[maxn],K[maxn],belong[maxn]; int l[1005],r[1005]; int main() { n=read();block=sqrt(n); for(int i=1;i<=n;i++){ K[i]=read(); } int cnt=n/block; if(n%block)cnt++; for(int i=1;i<=n;i++){ belong[i]=(i-1)/block+1; } for(int i=1;i<=cnt;i++){ l[i]=(i-1)*block+1; r[i]=(i)*block; } r[cnt]=n; for(int i=n;i>0;i--){ if(i+K[i]>n)st[i]=1,to[i]=0; else if(belong[i]==belong[i+K[i]]) st[i]=st[i+K[i]]+1,to[i]=to[i+K[i]]; else st[i]=1,to[i]=i+K[i]; } m=read(); while(m--){ int op=read(); if(op==1){ int pos=read(); pos++; int ans=0; while(true){ ans+=st[pos]; if(!to[pos])break; pos=to[pos]; } printf("%d\n",ans); } else{ int pos=read(),val=read(); pos++;K[pos]=val; for(int i=pos;i>=l[belong[pos]];i--){ if(belong[i]==belong[i+K[i]]) st[i]=st[i+K[i]]+1,to[i]=to[i+K[i]]; else st[i]=1,to[i]=i+K[i]; } } } return 0; } /* 4 1 2 1 1 3 1 1 2 1 1 1 1 */