2002: [Hnoi2010]Bounce 弹飞绵羊

二次联通门 : 2002: [Hnoi2010]Bounce 弹飞绵羊

#include <cstdio>
#include <cstdlib>

#define Max 200010

void read (int &now)
{
    now = 0;
    register char word = getchar ();
    while (word < ‘0‘ || word > ‘9‘)
        word = getchar ();
    while (word >= ‘0‘ && word <= ‘9‘)
    {
        now = now * 10 + word - ‘0‘;
        word = getchar ();
    }
}

inline int min (int a, int b)
{
    return a < b ? a : b;
}

struct Splay_Tree_Data
{
    int child[2];
    int father;

    int size;
    int Flandre;

};

int N;

int next[Max];
Splay_Tree_Data tree[Max];
int data[Max];

inline int swap (int &a, int &b)
{
    int now = a;
    a = b;
    b = now;
}

class Link_Cut_Tree_Type
{

    private :

        inline void Updata (int now)
        {
            tree[now].size = 1;
            tree[now].size += tree[tree[now].child[0]].size;
            tree[now].size += tree[tree[now].child[1]].size;
        }

        inline void Down (int now)
        {
            if (!tree[now].Flandre)
                return ;
            tree[now].Flandre ^= 1;
            tree[tree[now].child[0]].Flandre ^= 1;
            tree[tree[now].child[1]].Flandre ^= 1;
            swap (tree[now].child[0], tree[now].child[1]);
        }

        bool Is_Root (int now)
        {
            return tree[tree[now].father].child[0] != now && tree[tree[now].father].child[1] != now;
        }

        inline int Get_Pos (int now)
        {
            return tree[tree[now].father].child[1] == now;
        }

        inline void Rotate (int now)
        {
            int father = tree[now].father;
            int Grand = tree[father].father;
            int l, r = 0;
            l = tree[father].child[0] == now ? 0 : 1;
            r = l ^ 1;
            if (!Is_Root (father))
                tree[Grand].child[tree[Grand].child[0] != father] = now;
            tree[father].child[l] = tree[now].child[r];
            tree[now].child[r] = father;
            tree[father].father = now;
            tree[tree[father].child[l]].father = father;
            tree[now].father = Grand;
            Updata (father);
        }

        inline void Splay (int now)
        {
            int Count = 0;
            data[++Count] = now;
            for (int i = now; !Is_Root (i); i = tree[i].father)
                data[++Count] = tree[i].father;
            for (int i = Count; i; i --)
                Down (data[i]);
            while (!Is_Root (now))
            {
                int father = tree[now].father;
                int Grand = tree[father].father;
                if (!Is_Root (father))
                {
                    if (tree[father].child[0] == now ^ tree[Grand].child[0] == father)
                        Rotate (now);
                    else
                        Rotate (father);
                }
                Rotate (now);
                Updata (now);
            }
        }

        inline void Access (int now)
        {
            int pos = 0;
            while (now)
            {
                Splay (now);
                tree[now].child[1] = pos;
                pos = now;
                now = tree[now].father;
            }
        }

        inline void Make_Root (int now)
        {
            Access (now);
            Splay (now);
            tree[now].Flandre ^= 1;
        }

        inline void Link (int x, int y)
        {
            Make_Root (x);
            tree[x].father = y;
            Splay (x);
        }

        inline void Cut (int x, int y)
        {
            Make_Root (y);
            Access (x);
            Splay (x);
            tree[x].child[0] = 0;
            tree[y].father = 0;
        }

    public :

        inline void Do_First (int x)
        {
            Make_Root (N + 1);
            x ++;
            Access (x);
            Splay (x);
            printf ("%d\n", tree[tree[x].child[0]].size);
        }

        inline void Do_Second (int x, int y)
        {
            x ++;
            int now = min (N + 1, x + y);
            Cut (x, next[x]);
            Link (x, now);
            next[x] = now;
        }
};

Link_Cut_Tree_Type Make;
int M;

int main (int argc, char *argv[])
{
    read (N);
    int x;
    for (int i = 1; i <= N; i ++)
    {
        read (x);
        tree[i].father = x + i;
        tree[i].size = 1;
        if (tree[i].father > N + 1)
            tree[i].father = N + 1;
        next[i] = tree[i].father;
    }

    tree[N + 1].size = 1;
    read (M);
    for (int x, y, type, i = 1; i <= M; i ++)
    {
        read (type);
        read (x);
        if (type == 1)
            Make.Do_First (x);
        else
        {
            read (y);
            Make.Do_Second (x, y);
        }
    }
    return 0;
}
时间: 2024-10-27 12:15:25

2002: [Hnoi2010]Bounce 弹飞绵羊的相关文章

BZOJ 题目2002: [Hnoi2010]Bounce 弹飞绵羊(link cut tree)

2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 5421  Solved: 2863 [Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹

BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊( LCT )

LCT... ---------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i ) #define clr( x , c ) memset( x

bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 動態樹

2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 4055  Solved: 2172[Submit][Status] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki

【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊(lct)

(BZOJ挂了,还没在BZOJ测,先是在wikioi测过了,,) 囧.在军训时立志要学lct!!!这是一道lct的裸题,只有access操作(10行都没有啊亲...缩行大法的话,我就不说了..)(link操作相当于水过),其实lct很简单..想想都有点小激动...... lct用splay维护的话,一下就写好了..但是我在写lct的时候,发现了一些我原来splay的老问题,我原来也知道了的,就是将null的ch给赋值了,因为在rot操作里没有特判,所以导致了null的孩子被赋值了,导致我的lct

bzoj 2002 : [Hnoi2010]Bounce 弹飞绵羊 (LCT)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 题面: 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 15763  Solved: 8080[Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开

BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊:分块

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 题意: 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏. 游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞. 绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞. 为了使得游戏更

BZOJ 2002[Hnoi2010]Bounce 弹飞绵羊

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

bzoj 2002[Hnoi2010]Bounce 弹飞绵羊(分治分块)

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

●BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2002 题解: LCT 如果把弹跳的起点和终点连一条边,弹出去的与n+1号点连边, 则不难发现,整个图形成了一颗树, 同时需要支持树的修改(拆分,合并)和询问点的深度(该点到根的链上的点的个数), 所以LCT可以很轻松的解决本题. 代码: #include<cstdio> #include<cstring> #include<iostream> #include&l