• P3203 [HNOI2010]弹飞绵羊


    题目描述

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

    输入输出格式

    输入格式:

    第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1。

    接下来一行有n个正整数,依次为那n个装置的初始弹力系数。

    第三行有一个正整数m,

    接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。

    输出格式:

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    输入输出样例

    输入样例#1: 复制
    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1
    输出样例#1: 复制
    2
    3

    说明

    对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N=2e5+5;
    
    inline int read()
    {
        char c=getchar();int num=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num; 
    }
    
    int f[N],c[N][2],s[N]; 
    
    inline bool nroot(int x)
    {
        return c[f[x]][0]==x||c[f[x]][1]==x;
    }
    
    inline void pushup(int x)
    {
        s[x]=s[c[x][0]]+s[c[x][1]]+1;
    }
    
    inline void rotate(int x)
    {
        int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
        if(nroot(y))
            c[z][c[z][1]==y]=x;
        c[x][!k]=y,c[y][k]=w;
        if(w)
            f[w]=y;
        f[y]=x,f[x]=z;
        pushup(y);
    }
    
    inline void splay(int x)
    {
        int y,z;
        while(nroot(x))
        {
            y=f[x],z=f[y];
            if(nroot(y))
                rotate((c[y][0]==x)^(c[z][0]==y)?y:x);
            rotate(x);
        }
        pushup(x);
    }
    
    inline void access(int x)
    {
        for(int y=0;x;x=f[y=x])
            splay(x),c[x][1]=y,pushup(x);
    }
    
    int opt;
    int n,m,j,k;
    int main()
    {
    //    freopen("testdata.in","r",stdin);
    //    freopen("233.out","w",stdout);
        n=read();
        for(int i=1;i<=n;++i)
        {
            s[i]=1;
            k=read();
            if(i+k<=n)
                f[i]=i+k;    //没有被弹飞,连边 
        }
        m=read();
        while(m--)
        {
            opt=read();
            if(opt&1)
            {
                j=read(),++j;
                access(j),splay(j);    //将j与根打通,然后让j为根,直接查询
                printf("%d
    ",s[j]); 
            }
            else
            {
                j=read(),k=read(),++j;
                access(j),splay(j);
                c[j][0]=f[c[j][0]]=0;    //断边
                if(j+k<=n)
                    f[j]=j+k;    //连边
                pushup(j);
            }
        }
        return 0;
    }
  • 相关阅读:
    使用合理jQuery选择器查找DOM元素
    DOM对象和jQuery对象
    jQuery实现返回顶部
    行内元素,块级元素
    图片自适应缩放
    幽灵按钮
    background-attachment:fixed
    RegExp
    正则
    Date
  • 原文地址:https://www.cnblogs.com/lovewhy/p/9633876.html
Copyright © 2020-2023  润新知