洛谷 P3203 BZOJ 2002 [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。

 

输出格式:

 

对于每个i=1的情况,你都要输出一个需要的步数,占一行。

 

输入输出样例

输入样例#1: 复制
4
1 2 1 1
3
1 1
2 1 1
1 1
输出样例#1: 复制
2
3

说明

对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

解题思路

  LCT不会,或者分块。

  分成$\sqrt{n}$块,对于每个格子,维护三个值——$a[i]$第$i$个点的弹力系数,即弹射距离;$nxtn[i]$,弹射到下一个块所需的步数;$nxtp[i]$,从第i个点开始跳,直到离开这个块时的下一个位置(便于统计是一个块一个块地跳)。

  输入数据后,从后向前递推求出$nxtp[i]$和$nxtn[i]$。

  询问从$x$点开始,要弹飞所需的步数,就从$x$开始,利用$nxtp[i]$暴力跳块,用$nxtn[i]$暴力统计答案,直到飞了,输出答案。

  修改第$x$个点的弹力系数,就先把$a[x]$的值修改了,然后从后往前暴力递推$x$所在块的$nxtp[i]$和$nxtn[i]$。

源代码

 

 1 #include<stdio.h>
 2 #include<math.h>
 3 
 4 int n,t,m;
 5 int a[200010]/*弹力*/,nxtp[200010]/*到下一块的位置*/,nxtn[200010]/*到下一块的步数*/;
 6 
 7 
 8 int main()
 9 {
10     //freopen("test.in","r",stdin);
11     scanf("%d",&n);
12     t=sqrt(n);//块数
13     for(int i=0;i<n;i++)
14     {
15         scanf("%d",a+i);
16     }
17     for(int i=n-1;i>=0;i--)//i/t获得块数
18     {
19         if(i+a[i]>=n) nxtp[i]=n,nxtn[i]=1;
20         else if(i/t!=(i+a[i])/t) nxtp[i]=i+a[i],nxtn[i]=1;
21         else nxtp[i]=nxtp[i+a[i]],nxtn[i]=1+nxtn[i+a[i]];
22     }
23     scanf("%d",&m);
24     while(m--)
25     {
26         int opt;
27         scanf("%d",&opt);
28         if(opt==1)
29         {
30             int x;
31             scanf("%d",&x);
32             int ans=0;
33             while(x<n)
34             {
35                 ans+=nxtn[x];
36                 x=nxtp[x];
37             }
38             printf("%d\n",ans);
39         }
40         else
41         {
42             int x,y;
43             scanf("%d%d",&x,&y);
44             a[x]=y;
45             for(int i=(x/t+1)*t;i>=x/t*t;i--)
46             {
47                 if (i + a[i] >= n)
48                     nxtp[i] = n, nxtn[i] = 1;
49                 else if (i / t != (i + a[i]) / t)
50                     nxtp[i] = i + a[i], nxtn[i] = 1;
51                 else
52                     nxtp[i] = nxtp[i + a[i]], nxtn[i] = 1 + nxtn[i + a[i]];
53             }
54         }
55     }
56     return 0;
57 }

 

posted @ 2019-03-23 22:48  wawcac  阅读(165)  评论(0编辑  收藏  举报