2002: [Hnoi2010]Bounce 弹飞绵羊

来源:互联网 发布:关闭端口的命令 编辑:程序博客网 时间:2024/05/16 00:53

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

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

3

1 1

2 1 1

1 1

Sample Output

2

3

#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int maxn=200009;int m,n,pos[maxn],time[maxn],val[maxn];int main(){    scanf("%d",&n);    for(int i=0;i<n;i++)        scanf("%d",&val[i]);    int block=sqrt(n);    for(int i=n-1;i>=0;i--)    {        int tmp=i+val[i];        if(tmp>=n)//一次直接弹飞        {            pos[i]=-1;            time[i]=1;        }        else if(tmp>=(i/block+1)*block)//一次被弹到别的块中        {            pos[i]=tmp;            time[i]=1;            //至于这个地方为什么也是一,是因为我们只计算这个一个块内的元素            //所以后面的更新也只是在这一个单独的块中,如果不是从一开始计算,那么就会涉及到其他的块,那么分块的效率并不会有什么提高了        }        else        //还在此块中,由于从后往前计算,所以直接利用先前计算书来的结果        {            pos[i]=pos[tmp];            time[i]=time[tmp]+1;        }    }    scanf("%d",&m);    int op;    while(m--)    {        scanf("%d",&op);        int j,k;        if(op==1)        {            int ans=0;            scanf("%d",&j);            for(int i=j;i!=-1;i=pos[i])            {                ans+=time[i];            }            printf("%d\n",ans);        }        else        {            scanf("%d%d",&j,&k);            val[j]=k;            for(int i=j;i>=j/block*block;i--)            {                int tmp=i+val[i];                if(tmp>=n)                    pos[i]=-1,time[i]=1;                else if(tmp>=(i/block+1)*block)                    pos[i]=tmp,time[i]=1;                else                    pos[i]=pos[tmp],time[i]=time[tmp]+1;            }        }    }    return 0;}