BZOJ 2002 Bounce 弹飞绵羊(分块|暴力|)(困难)
来源:互联网 发布:淘宝被永久封能解开吗 编辑:程序博客网 时间:2024/04/27 23:14
Bounce 弹飞绵羊
Time Limit:10000MS Memory Limit:265216KB 64bit IO Format:%lld & %llu
Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Input
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
Sample Input
4 1 2 1 1 31 12 1 11 1
Sample Output
23
暴力://数据有漏洞
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,m;int num[200010],nxt[200010],step[200010];void xiugai(int l,int r){ for(int i=r;i>=l;i--) { if(nxt[i]>=n) { step[i]=1; continue; } if(nxt[i]<n&&step[nxt[i]]!=0) { step[i]=step[nxt[i]]+1; continue; } }}int main(){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&num[i]); memset(step,0,sizeof(step)); for(int i=0;i<n;i++) nxt[i]=i+num[i]; xiugai(0,n-1); scanf("%d",&m); int a,b,c; while(m--) { scanf("%d",&a); if(a==1) { scanf("%d",&b); printf("%d\n",step[b]); } else { scanf("%d%d",&b,&c); if(num[b]==c) continue; num[b]=c; nxt[b]=b+num[b]; xiugai(0,b); } } return 0;}
分块:
将序列分块,每块sqrt(n)个。
在每个块中维护f[i],to[i]
f[i] 表示跳几次可以跳出所在块
to[i] 表示跳出所在块后到达的位置。
在查询时,我们O(sqrt(n))的时间进行“整块”的模拟,可以得到结果。
在修改i时,我们只需维护一下(l[belong[i]]--i)的序列就可以了。
总复杂度:O(n*sqrt(n))
#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <cmath>using namespace std;int f[200005],to[200005],k[200005],bl[200005];int n,m,tot,l[200005];void Init(){ int i,j; scanf("%d",&n); m=int(sqrt(n)); j=m; for (i=0;i<n;i++) { if (j==m) j=1,tot++,l[tot]=i; else j++; scanf("%d",k+i); bl[i]=tot; } l[tot+1]=n; for (i=n-1;i>=0;i--) if (i+k[i]>=l[bl[i]+1]) f[i]=1,to[i]=i+k[i]; else f[i]=f[i+k[i]]+1,to[i]=to[i+k[i]];}int ask(int p){ int s=0; while (p<n) {s+=f[p];p=to[p];} return s;}void replace(int p,int k1){ k[p]=k1; int i; for (i=p;i>=l[bl[p]];i--) if (i+k[i]>=l[bl[i]+1]) f[i]=1,to[i]=i+k[i]; else f[i]=f[i+k[i]]+1,to[i]=to[i+k[i]];}void Work(){ int x,y,z; for (scanf("%d",&m);m--;) { scanf("%d",&x); if (x==1) { scanf("%d",&y); printf("%d\n",ask(y)); } else { scanf("%d%d",&y,&z); replace(y,z); } }}int main(){ Init(); Work(); return 0;}
0 0
- BZOJ 2002 Bounce 弹飞绵羊(分块|暴力|)(困难)
- BZOJ-2002-Bounce弹飞绵羊-分块
- BZOJ 2002 Bounce 弹飞绵羊 [分块]
- [Hnoi2010]Bounce 弹飞绵羊 分块暴力
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊|分块
- bzoj 2002 [Hnoi2010]Bounce 弹飞绵羊 [分块][特殊处理]
- Bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- [BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊:分块|LCT
- [BZOJ]2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- BZOJ 2002 Bounce 弹飞绵羊 —— 分块算法
- BZOJ 2002-Bounce 弹飞绵羊-(分块)
- HYSBZ 2002 Bounce 弹飞绵羊(分块)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
- 【BZOJ 2002】 [Hnoi2010]Bounce 弹飞绵羊
- 子网划分相关
- 基础正则表达式及grep的使用
- 在win20008上运行U890破解提示sorry,this application cannot run under a virtual machine
- 控制IOS状态栏的颜色
- poj1061 青蛙的约会 线性同余求解
- BZOJ 2002 Bounce 弹飞绵羊(分块|暴力|)(困难)
- 进制数转换和码实例
- HDU - 1171 Big Event in HDU
- windows 10卸载onedriver
- Oracle初探(三)
- 手势
- java volatile和atomic包的区别
- 维特比算法在隐马尔可夫模型中的应用
- IOS开发概述-10.事件处理概述