zoukankan      html  css  js  c++  java
  • bzoj2002Bounce 弹飞绵羊

    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

    分析:
    我们要把知道题转化为树形结构
    每个弹射装置都只能弹向一个固定的位置
    这是一对一的关系,就好像树上的爸爸和儿子
    所以就把每个节点当作儿子,连到下一个位置(爸爸)

    那要是弹飞了怎么办呢
    我们把所有弹飞的绵羊都连到一个不存在的位置(比如说n+1)
    整体思路还是很好想的
    然而只有一个点我想不明白
    就是,初始的时候正常连边,无论在查询时还是改变值时,x++
    望神犇能帮忙解释一下

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=100001;
    int pre[N],ch[N][2],q[N],size[N];
    bool rev[N];
    int n,a[N],m;
    
    int get(int bh)
    {
    
        return (ch[pre[bh]][0]==bh ? 0:1);  
    }
    
    int isroot(int bh)
    {
        return ch[pre[bh]][0]!=bh&&ch[pre[bh]][1]!=bh;
    }
    
    void push(int bh)
    {
        if (rev[bh])
        {
            rev[bh]^=1;
            rev[ch[bh][0]]^=1;
            rev[ch[bh][1]]^=1;
            swap(ch[bh][0],ch[bh][1]);
        }
    }
    
    void update(int bh)
    {
        if (bh)
        {
            size[bh]=1;
            if (ch[bh][0]) size[bh]+=size[ch[bh][0]];
            if (ch[bh][1]) size[bh]+=size[ch[bh][1]];
        }
    }
    
    void rotate(int bh)
    {
        int fa=pre[bh];
        int grand=pre[fa];
        int wh=get(bh);
        if (!isroot(fa)) ch[grand][ch[grand][0]==fa ? 0:1]=bh;
        ch[fa][wh]=ch[bh][wh^1];
        pre[ch[fa][wh]]=fa;
        ch[bh][wh^1]=fa;
        pre[fa]=bh;
        pre[bh]=grand;
        update(fa);
        update(bh);
    }
    
    void splay(int bh)
    {
        int top=0;
        q[++top]=bh;
        for (int i=bh;!isroot(i);i=pre[i])
            q[++top]=pre[i];
        while (top) push(q[top--]);
        for (int fa;!isroot(bh);rotate(bh))
            if (!isroot(fa=pre[bh]))
                rotate(get(bh)==get(fa) ? fa:bh);
    }
    
    void expose(int bh)
    {
        int t=0;
        while (bh)
        {
            splay(bh);
            ch[bh][1]=t;
            t=bh;bh=pre[bh];
        }
    }
    
    void makeroot(int bh)
    {
        expose(bh);
        splay(bh);
        rev[bh]^=1;
    }
    
    void link(int x,int y)
    {
        makeroot(x);
        pre[x]=y;
        splay(x);
    }
    
    void cut(int x,int y)
    {
        makeroot(x);
        expose(y);
        splay(y);
        ch[y][0]=pre[x]=0;
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            int u;
            scanf("%d",&u);
            if (i+u<=n) link(i,i+u),a[i]=i+u;
            else link(i,n+1),a[i]=n+1;
            size[i]=1;   //初始值不要忘 
        }
        size[n+1]=1;
        scanf("%d",&m);
        for (int i=1;i<=m;i++)
        {
            int opt,x,y;
            scanf("%d",&opt);
            if (opt==1)
            {
                scanf("%d",&x);
                x++;  //
                makeroot(n+1);   ///???
                expose(x);
                splay(x);
                printf("%d
    ",size[ch[x][0]]);
            }
            else 
            {
                scanf("%d%d",&x,&y);
                x++;  //
                cut(x,a[x]);  
                if (x+y<=n) a[x]=x+y;
                else a[x]=n+1;
                link(x,a[x]); 
            }
        }
        return 0;
    }
  • 相关阅读:
    5.线性回归算法
    作业14 15 手写数字识别-小数据集
    作业13 14 深度学习-卷积
    作业12 13-垃圾邮件分类2
    作业11 12.朴素贝叶斯-垃圾邮件分类
    作业10:11.分类与监督学习,朴素贝叶斯分类算法
    作业9、主成分分析
    作业8、特征选择
    作业7.逻辑回归实践
    作业6.逻辑归回
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673558.html
Copyright © 2011-2022 走看看