分块算法其实很神奇,就是把一个数列划分为sqrtN块,然后暴力就会得到意想不到的速度。
HNOI 2010 BZOJ 2002 弹飞绵羊
其实分块的真的没什么可讲的code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
struct hp{
int step,next;
}a[200001];
int n,m;
int ki[200001];
int block[501];
int main()
{
int i,per,t=0,opt,ans,x,k,j,dn;
scanf("%d",&n); per=sqrt(n);
for (i=1;i<=n;++i)
scanf("%d",&ki[i]);
block[0]=1; block[1]=n; t=0;
for (i=n;i>=1;--i)
{
t++;
if (i+ki[i]>block[block[0]])
{
a[i].step=1;
a[i].next=i+ki[i];
}
else
{
a[i].step=a[i+ki[i]].step+1;
a[i].next=a[i+ki[i]].next;
}
if (t==per)
{
t=0;
block[++block[0]]=i-1;
}
}
if (t==0) block[0]--;
for (i=1;i<=block[0]/2;++i)
swap(block[i],block[block[0]-i+1]);
scanf("%d",&m);
for (i=1;i<=m;++i)
{
scanf("%d",&opt);
if (opt==1)
{
ans=0;
scanf("%d",&x); x++;
while (x<=n)
{ans+=a[x].step; x=a[x].next; }
printf("%d\n",ans);
}
if (opt==2)
{
scanf("%d%d",&x,&k); x++;
t=upper_bound(block+1,block+block[0]+1,x)-block-1;
if (block[t]!=x) t++;
if (t>1) dn=block[t-1]+1;
else dn=1;
ki[x]=k;
for (j=x;j>=dn;--j)
{
if (j+ki[j]<=block[t])
{a[j].step=a[j+ki[j]].step+1; a[j].next=a[j+ki[j]].next;}
else
{a[j].step=1; a[j].next=j+ki[j];}
}
}
}
}