您的位置:首页 > 其它

bzoj2002: [Hnoi2010]Bounce 弹飞绵羊

2015-12-31 01:38 405 查看

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002

题意:中文题。。

分析:先将这个数组分块,每块大小为sqrt(n),然后设定f[i]表示从i出发到第一个和i不同块的点所需的步数,nex[i]表示那个第一个和i不同块的点的位置。然后我们每次查询的时候就能最多sqrt(n)次就能跳出n长度了,修改的话可以很明显的知道改变第i个点的系数是所影响的至于与i在同一个块并且在i前面的点,将这些点重构即可。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=200010;
const int MAX=151;
const int MOD=1000007;
const int MOD1=100000007;
const int MOD2=100000009;
const int INF=1000000000;
const double EPS=0.00000001;
typedef long long ll;
typedef unsigned long long ull;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int a
,c
,f
,nex
;
int main()
{
int i,n,m,u,v,w,clo,ans;
scanf("%d", &n);
for (i=1;i<=n;i++) scanf("%d", &a[i]);
clo=(int)sqrt(n);
for (i=1;i<=n;i++) c[i]=(i+clo-1)/clo;

for (i=n;i>0;i--)
if (i+a[i]>n) { f[i]=1;nex[i]=n+1; }
else if (c[i]!=c[i+a[i]]) { f[i]=1;nex[i]=i+a[i]; }
else { f[i]=f[i+a[i]]+1;nex[i]=nex[i+a[i]]; }

scanf("%d", &m);
while (m--) {
scanf("%d%d", &u, &v);v++;
if (u==1) {
ans=0;
while (v<=n) { ans+=f[v];v=nex[v]; }
printf("%d\n", ans);
} else {
scanf("%d", &w);a[v]=w;
w=(c[v]-1)*clo;
for (i=v;i>w;i--)
if (i+a[i]>n) { f[i]=1;nex[i]=n+1; }
else if (c[i]!=c[i+a[i]]) { f[i]=1;nex[i]=i+a[i]; }
else { f[i]=f[i+a[i]]+1;nex[i]=nex[i+a[i]]; }
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: