您的位置:首页 > 其它

[bzoj2002] [Hnoi2010]Bounce 弹飞绵羊

2016-08-13 21:55 246 查看

Problem link

[Hnoi2010]Bounce 弹飞绵羊

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

Solution

这题是一道LCT的例题,然而我怎么会LCT呢,于是就有分块大暴力搞定了。

首先高呼:分块大法好!分块大法好!分块大法好!

首先,分块,对于每一个点维护两个东西:跳出这个块需要多少部,以及跳出之后到了哪个点。

预处理O(N),要注意如果你打了O(nn√)的时间,在BZOJ的慢速评测下就会T

对于询问,最多只会跳n√次,时间复杂度为O(n√)

对于修改,暴力修改这个块内的点,一个块只有n√个点,时间复杂度O(n√)

总时间复杂度O(mn√)

(这句是一年以后加的)但是现在我会LCT了,点击这里进入

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define big 448
int n,a[201000],b[201000],c[201000],ac,be[201000];
int main()
{
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]),be[i]=(i-1)/big+1;
b
=n+1;c
=0;
for(int i=n;i;i--)
if(be[i]==be[i+a[i]]) c[i]=c[i+a[i]]+1,b[i]=b[i+a[i]];
else c[i]=1,b[i]=i+a[i];
for(scanf("%d",&ac);ac;ac--)
{
int jy;scanf("%d",&jy);
if(jy==1)
{
int x,ans=0;scanf("%d",&x);x++;
for(;x<=n;x=b[x]) ans+=c[x];
printf("%d\n",ans);
}
else
{
int x,y;scanf("%d%d",&x,&y);
int i=++x;c[i]=0;a[i]=y;
for(;x<=n&&be[x]==be[i];x=x+a[x]) c[i]++;b[i]=x;
for(int j=i-1;be[j]==be[i]&&j>0;j--) if(be[j+a[j]]==be[i]) c[j]=c[j+a[j]]+1,b[j]=b[j+a[j]];
}
}
}


另外吐槽

我恨BZOJ不能下载错误的点
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: