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

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 7896  Solved: 4124
    [Submit][Status][Discuss]

    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


    思路:这题可以用分块做,先分成sqrt(n)块,然后每一块记录左端点和右端点,然后对于每一个位置维护它跳到下一块或者直接跳到下几块的最小步数以及它跳到下一块的位置,然后询问的时候模拟一下就行了,修改的时候只要把这个位置所属的块的左端点到该点的信息修改下就行了。

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #include<string>
    #include<bitset>
    #include<algorithm>
    using namespace std;
    #define lson th<<1
    #define rson th<<1|1
    typedef long long ll;
    typedef long double ldb;
    #define inf 99999999
    #define pi acos(-1.0)
    #define Key_value ch[ch[root][1]][0]
    #define maxn 200050
    int k[maxn];
    int st[maxn],pt[maxn];  //st表示跳到下一个块要跳的步数,pt表示跳到下一个块或者再下一个块的位置
    int l[maxn],r[maxn],belong[maxn];
    
    int n;
    int cal(int x)
    {
        int i,j;
        int num=0;
        while(x<=n){
            num+=st[x];
            x=pt[x];
        }
        return num;
    }
    
    
    int main()
    {
        int m,i,j,f,c,d;
        while(scanf("%d",&n)!=EOF)
        {
            int len=sqrt(n);
            int num=n/len;
            if(n%len)num++;
    
            for(i=1;i<=num;i++){
                l[i]=(i-1)*len+1;
                r[i]=i*len;
            }
            r[num]=n;
    
            for(i=1;i<=n;i++){
                belong[i]=(i-1)/len+1;
            }
    
            for(i=1;i<=n;i++){
                scanf("%d",&k[i]);
            }
    
            for(i=n;i>=1;i--){
                if(i+k[i]>n){
                    st[i]=1;pt[i]=n+1;
                }
                else if(belong[i]==belong[i+k[i] ]  ){
                    st[i]=1+st[i+k[i] ];pt[i]=pt[i+k[i] ];
                }
                else{
                    st[i]=1;pt[i]=i+k[i];
                }
    
            }
    
    
            scanf("%d",&m);
            for(i=1;i<=m;i++){
                scanf("%d",&f);
                if(f==1){
                    scanf("%d",&c);
                    c++;
                    printf("%d
    ",cal(c));
                }
                else if(f==2){
                    scanf("%d%d",&c,&d);
                    c++;
                    k[c]=d;
                    for(j=c;j>=l[belong[c] ];j--){
                        if(j+k[j] >n){
                            st[j]=1;pt[j]=n+1;
                        }
                        else if(belong[j]==belong[j+k[j] ]){
                            st[j]=1+st[j+k[j] ];pt[j]=pt[j+k[j] ];
                        }
                        else{
                            st[j]=1;pt[j]=j+k[j];
                        }
                    }
                }
            }
        }
        return 0;
    }
    


  • 相关阅读:
    什么是Redis?简述它的优缺点?
    2021年最新盘点数据库MySql笔试题
    网易CTO:70%.NET开发,遇到这个问题就怂!
    近200篇机器学习&深度学习资料分享【转载】
    【转】为什么0.1无法被二进制小数精确表示?
    【Leetcode-easy】Remove Element
    【Leetcode-easy】Remove Duplicates from Sorted Array
    【LeetCode-easy】Merge Two Sorted Lists
    【Leetcode-easy】Valid Parentheses
    【Leetcode-easy】Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/herumw/p/9464480.html
Copyright © 2011-2022 走看看