zoukankan      html  css  js  c++  java
  • 「BZOJ2002」[HNOI2010] Bounce 弹飞绵羊

    http://hzwer.com/3505.html

    某天,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<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int mxn=200020;
    int read(){
        int 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 block,cnt;
    int B[mxn],L[mxn],R[mxn];
    int nxt[mxn],k[mxn],w[mxn];
    int n,m;
    int clc(int st)
    {
        int res=0;
        while(st<=n && st)
    	{
            res+=w[st];
            st=nxt[st];
        }
        return res;
    }
    int main()
    {
        n=read();
        int i,j;
        for(i=1;i<=n;i++)
    	    k[i]=read();
        block=sqrt(n);
        cnt=(n-1)/block+1;
        for(i=1;i<=cnt;i++)
    	{
            L[i]=R[i-1]+1;
            R[i]=i*block;
    //        printf("L:%d R:%d
    ",L[i],R[i]);
        }
        R[cnt]=min(R[cnt],n);
        for(i=1;i<=n;i++)
    	    B[i]=(i-1)/block+1;
        for(i=n;i;i--)
    	{
            if(i+k[i]>n)
    		   w[i]=1;
            else 
    		if(B[i]==B[i+k[i]]) //如果属于同一块
    		{
                    w[i]=w[i+k[i]]+1;
                    //w[i]=j,代表从第i个位置跳多少步,跳出本块
                    nxt[i]=nxt[i+k[i]];
                    //nxt[i]=j,代表跳出本块后,跳到哪个位置
            }
            else //如果不在同一块,则一步就可以跳出分块
    			{
                    w[i]=1;
                    nxt[i]=i+k[i];
                }
        }
        m=read();
        int op,x,y;
        while(m--)
    	{
            op=read();
            if(op==1)
    		{
                x=read()+1;
                printf("%d
    ",clc(x));
            }
            else
    		{
                x=read()+1;y=read();
                k[x]=y;
                for(i=x;i>=L[B[x]];i--)
    			{
                    if(B[i]==B[i+k[i]])
    				{
                        w[i]=w[i+k[i]]+1;
                        nxt[i]=nxt[i+k[i]];
                    }
                    else
    				{
                        w[i]=1;
                        nxt[i]=i+k[i];
                    }
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    The Future of Middleware and the BizTalk Roadmap
    FW: How to spawn a process that runs under the context of the impersonated user in Microsoft ASP.NET pages
    Strips illegal Xml characters
    luogu P2280 激光炸弹(二维前缀和)
    luogu P2704 炮兵阵地(经典状态压缩DP)
    SP1716 GSS3 Can you answer these queries III (线段树维护最大连续子段和)
    二分图判定、匹配问题
    C++语法综合 | 基于char*设计一个字符串类MyString
    luogu P1044 火车进出栈问题(Catalan数)
    C++设计模式 | 三种设计模式基础
  • 原文地址:https://www.cnblogs.com/cutemush/p/12849219.html
Copyright © 2011-2022 走看看