zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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;
    }
  • 相关阅读:
    我要变牛逼
    java web
    导师选择
    2.1进程
    来到博客园写东西的第一天
    简单的页面布局
    html5
    第一个servlet程序
    java2D
    字节流 文件字节流 缓冲字节流
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6958429.html
Copyright © 2011-2022 走看看