P3203 [HNOI2010]BOUNCE 弹飞绵羊
题目描述
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
输入输出格式
输入格式:
第一行包含一个整数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
输出格式:
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
输入输出样例
输入样例#1:
4 1 2 1 1 3 1 1 2 1 1 1 1
输出样例#1:
View Code
2 3
思路:
分块什么的
坑点:
1.注意是从0号元素开始!!!
2.在luogu上最好不要用next数组...
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int M = 200000; const int N = 1000; int n,m; int k[M],steps[M],nxt[M]; ///step数组存的是需要多少步跳出当前块 ///next数组存的是跳到(下一块)的下一个点 int len,ks,kuai[M],l[N],r[N];///分块 void Builds() { ///块的长度 len=sqrt(n); ///块的个数 ks=len; if(n%ks) ks++; ///分块 for(int i=0;i<n;i++) kuai[i]=(i-1)/len; /* 因为块数是从0号开始计数的, 当i==(√n)时如果不进行-1, 会被分到第一块, 但事实上它是第0块的, 所以进行-1 */ for(int i=1;i<=ks;i++) { l[i]=(i-1)*len; ///r[i]=i*len-1中-1的原因是: ///因为数组是从0号开始储存的 r[i]=i*len-1; } ///将最后一块的右端手动设置为n的长度 r[ks]=n; for(int i=n-1;i>=0;i--) { int now=i+k[i]; ///如果下一步跳到的地方已经跳出最远的距离n的话 if(now>=n) ///更新步数:跳一步就跳出去 steps[i]=1, ///这里重要!需要手动将next数组设置一个不可能出现的数值 nxt[i]=-1; else ///假如在同一块中 if(kuai[i]==kuai[now]) ///更新步数,i的步数由now的步数多跳一步来到当前(点)位置 steps[i]=steps[now]+1, ///更新接下来跳到的点是... nxt[i]=nxt[now]; else ///不在一块中 steps[i]=1, ///跳到now这个点 nxt[i]=now; } } int ask(int pre) { int ans=0; while(pre!=-1) { ans+=steps[pre]; pre=nxt[pre]; } return ans; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&k[i]); ///开始分块 Builds(); scanf("%d",&m); for(int i=0,c;i<m;i++) { scanf("%d",&c); if(c==1) { int pre; scanf("%d",&pre); printf("%d ",ask(pre)); } else { int pre,ki; scanf("%d%d",&pre,&ki); ///更新k值 k[pre]=ki; ///因为更改k之后只会影响到当前块,并且只会影响他前面的 for(int j=pre;j>=l[kuai[pre]];j--) { int now=j+k[j]; if(now>=n) steps[j]=1, nxt[j]=-1; else if(kuai[j]==kuai[now]) steps[j]=steps[now]+1, nxt[j]=nxt[now]; else steps[j]=1, nxt[j]=now; } } } return 0; }