BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊

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

 

 

/*
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
    
    用LCT维护子树大小

    每弹跳一次;
    树中+1个节点(本次弹跳终点);
    这样弹跳次数就转化为了子树的大小
    
    注意当下标大于N+1时设为N 

    最初,对于每个反弹装置i,由i向min(n+1,i+k[i])连一条边,i指向min(n+1,i+k[i]) 

    即这里从树根到往下是弹跳的逆过程
    
    数组版的思路和代码都是参考的xxy dalao 
*/
#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;
}

 

 

 

 

/*
    2002: [Hnoi2010]Bounce 弹飞绵羊
    
    Link_Cut_Tree 指针版
    
    mmp, 终于调出来了。。。
    
    指针版比数组版慢300ms
    空间比数组版大3倍左右
    
    那么指针和数组的优劣就很清楚了。。。
    
    那么我就写指针了!! 
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>

#define Max 200009

int N;

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
{
    Splay_Tree_Data *child[2];
    Splay_Tree_Data *father;

    int size;
    int Flandre;

    Splay_Tree_Data ()
    {
        size = 1;
        Flandre = 0;
        father = NULL;
        child[0] = child[1] = NULL;
    }

    inline void Updata ()
    {
        size = 1;
        if (child[0])
            size += child[0]->size;
        if (child[1])
            size += child[1]->size;
    }

    inline void Down ()
    {
        if (!Flandre)
            return ;
        std :: swap (child[0], child[1]);
        Flandre = 0;
        if (child[0])
            child[0]->Flandre ^= 1;
        if (child[1])
            child[1]->Flandre ^= 1;
    }

    inline int Get_Pos ()
    {
        return this->father->child[1] == this;
    }

    inline int Is_Root ()
    {
        return !(this->father) || (this->father->child[0] != this && this->father->child[1] != this);
    }
};
Splay_Tree_Data *data[Max];
Splay_Tree_Data *node[Max];

int to[Max];

class Link_Cut_Tree_Type
{
    private :
        
        inline void Rotate (Splay_Tree_Data *now)
        {
            int pos = now->Get_Pos () ^ 1;
            Splay_Tree_Data *Father = now->father;
            Father->child[pos ^ 1] = now->child[pos];
            if (now->child[pos])
                now->child[pos]->father = Father;
            now->father = Father->father;
            if (!(Father->Is_Root ()))
                now->father->child[Father->Get_Pos ()] = now;
            Father->father = now;
            now->child[pos] = Father;
            Father->Updata ();
            now->Updata ();
        }

        inline void Splay (Splay_Tree_Data *now)
        {
            int Count = 0;
            for (Splay_Tree_Data *Father = now; ; Father = Father->father)
            {
                data[++Count] = Father;
                 if (Father->Is_Root ())
                    break;
            }
            for (; Count >= 1; -- Count)
                data[Count]->Down ();
            for (; !(now->Is_Root ()); Rotate (now))
                if (!(now->father->Is_Root ()))
                    Rotate (now->Get_Pos () == now->father->Get_Pos () ? now->father : now);
            now->Updata ();
        }

        inline void Access (Splay_Tree_Data *now)
        {
            for (Splay_Tree_Data *Father = NULL; now; Father = now, now = now->father)
            {
                Splay (now);
                now->child[1] = Father;
                now->Updata ();
            }
        }

        inline void Make_Root (Splay_Tree_Data *now)
        {
            Access (now);
            Splay (now);
            now->Flandre ^= 1;
        }

        inline void Cut (Splay_Tree_Data *x, Splay_Tree_Data *y)
        {
            Make_Root (x);
            Access (y);
            Splay (y);
            x->father = y->child[0] = NULL;
            y->Updata ();
        }

        inline void Link (Splay_Tree_Data *x, Splay_Tree_Data *y)
        {
            Make_Root (x);
            x->father = y;
        }

    public :

        inline void Link (int x, int y)
        {
            if (node[x] == NULL)    
                node[x] = new Splay_Tree_Data ();
            if (node[y] == NULL)
                node[y] = new Splay_Tree_Data ();
            node[x]->father = node[y];
        } 

        inline void Make_First (int x)
        {
            if (node[x] == NULL)
                node[x] = new Splay_Tree_Data ();
            if (node[N + 1] == NULL)
                node[N + 1] = new Splay_Tree_Data;
            Make_Root (node[N + 1]);
            Access (node[x]);
            Splay (node[x]);
            printf ("%d\n", node[x]->child[0]->size);
        }

        inline void Make_Second (int x, int y)
        {
            if (node[x] == NULL)
                node[x] = new Splay_Tree_Data;
            if (node[y] == NULL)
                node[y] = new Splay_Tree_Data;
            if (node[min (x + to[x], N + 1)] == NULL)
                node[min (x + to[x], N + 1)] = new Splay_Tree_Data;
            Cut (node[x], node[min (x + to[x], N + 1)]);
            to[x] = y;
            if (node[min (x + to[x], N + 1)] == NULL)
                node[min (x + to[x], N + 1)] = new Splay_Tree_Data;
            Link (node[x], node[min (x + to[x], N + 1)]);
        }
};

Link_Cut_Tree_Type Make;

int main (int argc, char *argv[])
{
    read (N);
    for (int i = 1; i <= N; i++)
    {
        read (to[i]);
        Make.Link (i, min (i + to[i], N + 1));
    }
    int type, x, y;
    int M;
    for (read (M); M--; )
    {
        read (type);
        if (type == 1)
        {
            read (x);
            Make.Make_First (x + 1);
        }
        else
        {
            read (x);
            read (y);
            Make.Make_Second (++ x, y);
        }
    }
    return 0;
}

 

posted @ 2017-06-07 18:05  ZlycerQan  阅读(176)  评论(0编辑  收藏