[BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊(分块)

Description

某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

Solution

分块大法好…迷之优雅的暴力

维护每个点跳到下一个块的位置和所需要的次数 修改和查询应该都是sqrt(n)吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#define MAXN 200002
using namespace std;
int n,m,init,k[MAXN],bump[MAXN],cnt[MAXN];
int main()
{
    scanf("%d",&n);
    init=(int)sqrt(n+0.1);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&k[i]);
        bump[i]=i+k[i];
        cnt[i]=1;
    }
    for(int i=n-1;i>=0;i--)
    {
        int t;
        while(bump[i]<min((i/init+1)*init,n))
        {
            t=bump[i];
            bump[i]=bump[t];
            cnt[i]+=cnt[t];
        }
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,ans,t;
        scanf("%d%d",&x,&y);
        if(x==1)
        {
            ans=0,t=y;
            while(t<n)
            {
                ans+=cnt[t];
                t=bump[t];
            }
            printf("%d\n",ans);
        }
        else
        {
            scanf("%d",&k[y]);
            int s=y/init*init;
            for(int j=y;j>=s;j--)
            {
                bump[j]=j+k[j];
                cnt[j]=1;
                while(bump[j]<min((j/init+1)*init,n))
                {
                    t=bump[j];
                    bump[j]=bump[t];
                    cnt[j]+=cnt[t];
                }
            }
        }
    }
    return 0;
} 

 

posted @ 2017-04-21 02:04  Zars19  阅读(223)  评论(0编辑  收藏  举报