[HNOI2010]弹飞绵羊

分块+线性DP

维护从某个点出发跳出这个块会跳到哪,需要几步即可

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"cmath"
using namespace std;

const int MAXN=2e5+5;
const int MAXM=505;

int n,m,siz;
int a[MAXN],v[MAXN],l[MAXN],r[MAXN],id[MAXN],g[MAXN];
int blk[MAXM];

int cqr(int x)
{
	int sum=0,ct=x;
	while(ct<n) sum+=g[ct],ct=v[ct];
	return sum;
}

void cchg(int x,int val)
{
	a[x]=val;
	for(int i=x;i>=l[x];--i){
		v[i]=min(a[i]+i,n);
		if(v[i]>r[i]) g[i]=1;
		else g[i]=g[v[i]]+1,v[i]=v[v[i]];
	}return;
}

int main()
{
	scanf("%d",&n);siz=sqrt(n);v[n]=n;
	for(int i=0;i<n;++i){
		scanf("%d",&a[i]);
		id[i]=i/siz;
		l[i]=id[i]*siz;
		r[i]=min((id[i]+1)*siz-1,n-1);
	}for(int i=n-1;i>=0;--i){
		v[i]=min(a[i]+i,n);
		if(v[i]>r[i]) g[i]=1;
		else g[i]=g[v[i]]+1,v[i]=v[v[i]];
	}scanf("%d",&m);
	while(m--){
		int c,x,y;scanf("%d",&c);
		if(c==1) scanf("%d",&x),printf("%d\n",cqr(x));
		else scanf("%d%d",&x,&y),cchg(x,y);
	}return 0;
}
posted @ 2018-11-28 20:26  A·H  阅读(107)  评论(0编辑  收藏  举报