zoukankan      html  css  js  c++  java
  • bzoj 2002

    2002: [Hnoi2010]Bounce 弹飞绵羊

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 3848  Solved: 2051
    [Submit][Status]

    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


    1 2 1 1 
    3
    1 1
    2 1 1
    1 1

    Sample Output

    2
    3
     
     
    我的第一题LCT。现在仍理解得不是很透彻。
     
    LCT:通过access操作把一棵树分解成若干条路径,用splay维护路径的信息,使复杂度达到logN级别
     
    这题只有两个操作:
    1.询问某节点的深点
    2.修改某个节点的父亲
     
    只用了access操作.
     
    继续努力吧。LCT还要多写几题啊.
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    
    //fa[i],i如果不是splay的根,则表示i在splay中的父节点,否则表示i所splay表示的链连接的树中的父节点
    //root[i],表示i是否是splay的根
    
    struct tree{
        int ls,rs;
    }tr[200011];
    
    int fa[200011],size[200011];
    bool root[200011];
    int i,n,x,z,kind,m;
    
    void update(int x)
    {
        size[x]=size[tr[x].ls]+size[tr[x].rs]+1;
    }
    
    void right_rotate(int x)
    {
        int y,z;
        y=tr[x].ls;
        z=tr[y].rs;
        tr[x].ls=z;
        tr[y].rs=x;
        fa[z]=x;
        if(tr[fa[x]].ls==x)tr[fa[x]].ls=y;
        if(tr[fa[x]].rs==x)tr[fa[x]].rs=y;
        fa[y]=fa[x];
        fa[x]=y;
        if(root[x]==true){
            root[y]=true;
            root[x]=false;
        }
        update(x);
        update(y);
    }
    
    void left_rotate(int x)
    {
        int y,z;
        y=tr[x].rs;
        z=tr[y].ls;
        tr[x].rs=z;
        tr[y].ls=x;
        fa[z]=x;
        if(tr[fa[x]].ls==x)tr[fa[x]].ls=y;
        if(tr[fa[x]].rs==x)tr[fa[x]].rs=y;
        fa[y]=fa[x];
        fa[x]=y;
        if(root[x]==true){
            root[y]=true;
            root[x]=false;
        }
        update(x);
        update(y);
        
    }
    
    void splay(int x)
    {
        while(root[x]==false){
            if(tr[fa[x]].rs==x)left_rotate(fa[x]);
            else right_rotate(fa[x]);
        }
    }
    
    void access(int x)
    {
        int z;
        splay(x);
        while(fa[x]!=0){
            z=fa[x];
            splay(z);
            root[tr[z].rs]=true;
            root[x]=false;
            tr[z].rs=x;
            update(z);
            x=z;
            splay(x);
        }
    }
    
    int main()
    {
        memset(root,true,sizeof(root));
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d",&x);
            fa[i]=i+x;
            if(fa[i]>n)fa[i]=n+1;
        }
        for(i=1;i<=n+1;i++)size[i]=1;
        scanf("%d",&m);
        for(i=1;i<=m;i++){
            scanf("%d",&kind);
            if(kind==1){
                scanf("%d",&x);
                x++;
                access(x);
                splay(x);
                printf("%d
    ",size[tr[x].ls]);
            }
            else{
                scanf("%d%d",&x,&z);
                x++;
                access(x);
                splay(x);
                fa[tr[x].ls]=fa[x];
                root[tr[x].ls]=true;
                tr[x].ls=0;
                size[x]=size[tr[x].rs]+1;
                fa[x]=x+z;
                if(fa[x]>n)fa[x]=n+1;
            }
        }
    }
  • 相关阅读:
    重新格式化部门表
    从不订购的客户
    回文数
    shell中的双括号表达式
    shell中的if语句
    shell
    view的生命周期
    shell中的数学运算
    shell中的expr命令
    shell中的退出状态码
  • 原文地址:https://www.cnblogs.com/applejxt/p/3903438.html
Copyright © 2011-2022 走看看