[bzoj2002] [Hnoi2010]Bounce 弹飞绵羊

    xiaoxiao2025-01-30  6

    [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]=n+1;c[n]=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不能下载错误的点

    转载请注明原文地址: https://ju.6miu.com/read-1295920.html
    最新回复(0)