zoukankan      html  css  js  c++  java
  • 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块

    【bzoj2002】[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

    题解

      对每一个点记录其下一个到达的位置及从这个位置到下一个分块所用的步数;

    代码

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <queue>
    #include <typeinfo>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    //***************************
    int n,m,a[200005],pos[200005],ans[200005],next[200005];
    int block;
    int main()
    {
    
        scanf("%d",&n);block=int(sqrt(n));
        for(int i=1;i<=n;i++){
           scanf("%d",&a[i]);
           pos[i]=(i-1)/block+1;
        }
        for(int i=n;i>=1;i--){
            if(a[i]+i>n)ans[i]=1;
            else if(pos[i]==pos[a[i]+i])ans[i]=ans[a[i]+i]+1,next[i]=next[a[i]+i];
            else ans[i]=1,next[i]=a[i]+i;
        }
        if(n%block)m=n/block+1;
        else m=n/block;
        int q=read();
        for(int i=1;i<=q;i++)
        {
            int x,y;
            int tt=read();
            if(tt==1){
                    x=read();x++;
                int sum=0;
                while(1)
                {
                    sum+=ans[x];
                    if(next[x]==0)break;
                    x=next[x];
                }
                printf("%d
    ",sum);
            }
            else {
                    x=read();
                    x++;
                   y=read();
                   a[x]=y;
                for(int i=x;i>(pos[x]-1)*block;i--){
                    if(pos[i]==pos[a[i]+i]){///== if(x==a[i]+i){
                        ans[i]=ans[a[i]+i]+1,next[i]=next[i+a[i]];
                    }else ans[i]=1,next[i]=a[i]+i;
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    JQuery缓冲加载图片插件lazyload.js的使用方法
    CSS3阴影 box-shadow的使用和技巧总结
    HTML符号大全
    TouchSlide
    响应式图片的3种解决方案
    ECMAScript arguments 对象
    call() 方法 和 apply()方法详解
    字体图标 iconfont cssfont
    响应式样式
    1-微信小程序创建项目
  • 原文地址:https://www.cnblogs.com/zxhl/p/4738208.html
Copyright © 2011-2022 走看看