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

    2002: [Hnoi2010]Bounce 弹飞绵羊

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 13190  Solved: 6712
    [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
    分析:这道题可以用分块的做法,详见:传送门. 同时,它又是一道LCT的裸题. 
       如果点i能跳到点j,那么让j当i的父亲,如果从i能跳出去,那么让n+1当点i的父亲. 这样每次询问的话,让n+1当根,将i号点splay到根上,左子树的大小就是答案了.  修改就是Link和Cut操作了.
       为什么求左子树大小?因为Access时每次都把x当作x的父亲的右儿子. splay(x),n+1一定位于x的左子树中.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 200010;
    int n,a[maxn],fa[maxn],m,sizee[maxn],son[maxn][2],rev[maxn],to[maxn],sta[maxn];
    
    void fan(int x)
    {
        swap(son[x][0],son[x][1]);
        rev[x] ^= 1;
    }
    
    void pushdown(int x)
    {
        if (rev[x])
        {
            fan(son[x][0]);
            fan(son[x][1]);
            rev[x] = 0;
        }
    }
    
    void pushup(int x)
    {
        sizee[x] = 1;
        if (son[x][0])
            sizee[x] += sizee[son[x][0]];
        if (son[x][1])
            sizee[x] += sizee[son[x][1]];
    }
    
    bool is_root(int x)
    {
        return son[fa[x]][0] != x && son[fa[x]][1] != x;
    }
    
    bool get(int x)
    {
        return son[fa[x]][1] == x;
    }
    
    void turn(int x)
    {
        int y = fa[x];
        int z = fa[y];
        int temp = get(x);
        if (!is_root(y))
            son[z][son[z][1] == y] = x;
        fa[x] = z;
        son[y][temp] = son[x][temp ^ 1];
        fa[son[y][temp]] = y;
        son[x][temp ^ 1] = y;
        fa[y] = x;
        pushup(y);
        pushup(x);
    }
    
    void splay(int x)
    {
        int top = 0;
        sta[++top] = x;
        for (int y = x; !is_root(y);y = fa[y])
            sta[++top] = fa[y];
        for (int i = top; i >= 1; i--)
            pushdown(sta[i]);
        for (int temp;!is_root(x);turn(x))
        {
            if (!is_root(temp = fa[x]))
            {
                if (get(temp) == get(x))
                    turn(temp);
                else
                    turn(x);
            }
        }
    }
    
    void Access(int x)
    {
        int t = 0;
        for (;x;t = x,x = fa[x])
        {
            splay(x);
            son[x][1] = t;
            pushup(x);
        }
    }
    
    void Reverse(int x)
    {
        Access(x);
        splay(x);
        fan(x);
    }
    
    int query(int x)
    {
        Reverse(n + 1);
        Access(x);
        splay(x);
        return sizee[son[x][0]];
    }
    
    void Link(int x,int y)
    {
        Reverse(x);
        fa[x] = y;
        splay(x);
    }
    
    void Cut(int x,int y)
    {
        Reverse(x);
        Access(y);
        splay(y);
        son[y][0] = fa[x] = 0;
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
            if (i + a[i] > n)
                to[i] = n + 1;
            else
                to[i] = i + a[i];
            Link(i,to[i]);
        }
        scanf("%d",&m);
        while (m--)
        {
            int op,x,y;
            scanf("%d%d",&op,&x);
            x++;
            if (op == 1)
                printf("%d
    ",query(x));
            else
            {
                scanf("%d",&y);
                Cut(x,to[x]);
                to[x] = x + y;
                if (to[x] > n)
                    to[x] = n + 1;
                Link(x,to[x]);
            }
        }
    
        return 0;
    }
       
  • 相关阅读:
    【转】PG数据库高级用法 之 12306 -- 链接
    javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath
    java图片识别 [Tesseract-OCR]
    MongoDB从环境搭建到代码编程(Window 环境)
    webDriver + Firefox 浏览器 完美兼容
    SQLServer 将日期改造成标准日期格式(如: 2016/6 ->201606)
    Angularjs+bootstrap 实现横向滑屏
    js数组长度
    Angularjs 跨域post数据到springmvc
    Oracle 18c 数据库中scott用户不存在的解决方法
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8529979.html
Copyright © 2011-2022 走看看