• BZOJ 4817: [Sdoi2017]树点涂色


    二次联通门 : BZOJ 4817: [Sdoi2017]树点涂色

    /*
        BZOJ 4817: [Sdoi2017]树点涂色
        
        考场上打的暴力
        
        本想着拿个暴力分, 结果惨遭RE爆零。。
        
        如今学了LCT, 再回过头来看这个题。。
        
        好吧还是不会。。。
        
        做法: 
        操作1其实就是Access操作
            一条路径上的不同颜色数就是LCT中徐变得数量加1
            在做 Access操作时, 考率当前的点now, 那么now连向的节点子树权值会+1
            下面的子树的权值减1就好了 
            
            操作2就是x点的权值 + y点的权值 - 2*Lca(x,y)的权值
             
            操作3直接用链剖 + Dfs序搞就好了 
        
        根据势能分析  轻重边切换的次数是O(nlogn)的
        总复杂度为O(nlog2n). 
        
        但是。。。
        但是。。。
        为什么有两个点的第一个3操作会出错答案多1啊。。。
        绝望啊、。
        打表啊。。 
    */
    #include <cstdio>
    #include <cstdlib>
    #include <malloc.h>
    #define Max 400010
    
    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 ();
        }
    }
    
    struct Edge_Data
    {
        int to;
        int next;
    };
    
    int N, M;
    Edge_Data edge[Max << 2];
    
    struct Splay_Tree_Data 
    {
        
        Splay_Tree_Data *child[2];
        
        Splay_Tree_Data *father;
        
        int Id;
        inline int Is_Root ()
        {
            return !(this->father) || (this->father->child[0] != this && this->father->child[1] != this);
        }
        
        Splay_Tree_Data (int __x) : Id (__x)
        {
            child[0] = child[1] = NULL;
            father = NULL;
        }
        
        inline int Get_Pos ()
        {
            return this->father->child[1] == this;
        }
    };
    
    inline int min (int a, int b)
    {
        return a < b ? a : b;
    }
    
    inline int max (int a, int b)
    {
        return a > b ? a : b;
    }
    
    Splay_Tree_Data *node[Max];
    int deep[Max];
    
    int tree_end[Max];
    
    struct Segment_Tree_Data
    {
        Segment_Tree_Data *Left, *Right;
        
        int l, r;
        int Mid;
        
        int key, Flandre;
        
        inline void Up ()
        {
            this->key = max (this->Left->key, this->Right->key);
            return ;
        }
        
        inline void Down ()
        {
            this->Left->Flandre += this->Flandre;
            this->Right->Flandre += this->Flandre;
            
            this->Left->key += this->Flandre;
            this->Right->key += this->Flandre;
            
            this->Flandre = 0;
            return ;
        }
        
        Segment_Tree_Data (int __l, int __r) : l (__l ), r (__r)
        {
            this->Mid = __l + __r >> 1;
            Left = Right = NULL;
            
            key = 0;
            Flandre = 0;
        }
    };
    
    
    int tree_number[Max];
    
    int what_[Max];
    
    class Segment_Tree_Type
    {
        private :
            
            Segment_Tree_Data *Root;
            
            void __Build_ (Segment_Tree_Data *&now, int l, int r)
            {
                now = new Segment_Tree_Data (l, r);
                if (l == r)
                {
                    now->key = deep[what_[l]];
                    return ;
                }
                __Build_ (now->Left, l, now->Mid);
                __Build_ (now->Right, now->Mid + 1, r);
                now->Up ();
            }
            
            int __Query_Maxn_ (Segment_Tree_Data *&now, int l, int r)
            {
                if (l <= now->l && now->r <= r)
                    return now->key;
                int res = 0;
                if (now->Flandre)
                    now->Down ();
                now->Up ();
                if (l <= now->Mid)
                    res = max (__Query_Maxn_ (now->Left, l, min (now->Mid, r)), res);
                if (r > now->Mid)
                    res = max (__Query_Maxn_ (now->Right, max (now->Mid + 1, l), r), res);
                return res;
            }
            
            void __Change_ (Segment_Tree_Data *&now, int l, int r, int to)
            {
                if (l <= now->l && now->r <= r)
                {
                    now->Flandre += to;
                    now->key += to;
                    return ;
                }
                if (now->Flandre)
                    now->Down ();
                if (l <= now->Mid)
                    __Change_ (now->Left, l, min (now->Mid, r), to);
                if (r > now->Mid)
                    __Change_ (now->Right, max (now->Mid + 1, l), r, to);
                now->Up ();
            }
            
            int __Query_ (Segment_Tree_Data *&now, int pos)
            {
                if (now->l == now->r)
                    return now->key;
                if (now->Flandre)
                    now->Down ();
                now->Up ();
                if (pos <= now->Mid)
                    return __Query_ (now->Left, pos);
                else 
                    return __Query_ (now->Right, pos);
            }
            
        public :
            
            inline void Build (int l, int r)
            {
                __Build_ (Root, l, r);
                return ;
            }
            
            inline void Change (int l, int r, int to)
            {
                __Change_ (Root, l, r, to);
                return ;
            }
            
            inline int Query_Maxn (int now)
            {
                return __Query_Maxn_ (Root, tree_number[now], tree_end[now]);
            }
            
            inline int Query (int x)
            {
                return __Query_ (Root, x);
            }
            
    };
    
    inline int swap (int &a, int &b)
    {
        int now = a;
        a = b;
        b = now;
    }
    
    Segment_Tree_Type Seg_Tree;
    
    int Edge_Count ;
    int edge_list[Max];
    
    inline int Add_Edge (int from, int to)
    {
        Edge_Count ++;
        edge[Edge_Count].to = to;
        edge[Edge_Count].next = edge_list[from];
        edge_list[from] = Edge_Count;
        Edge_Count ++;
        edge[Edge_Count].to = from;
        edge[Edge_Count].next = edge_list[to];
        edge_list[to] = Edge_Count;
    }
    
    class Tree_Chain_Get_Type
    {
        private :
    
            int father[Max];
            int size[Max];
            int up_[Max];
            
            int Count;
            
            void Dfs_1 (int now, int __father)
            {
                int pos = Count ++;
                deep[now] = deep[__father] + 1;
                father[now] = __father;
                
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != __father)
                        Dfs_1 (edge[i].to, now);
                
                size[now] = Count - pos;
            }
            
            void Dfs_2 (int now, int chain)
            {
                int pos = 0;
                up_[now] = chain;
                tree_number[now] = ++Count;
                what_[Count] = now;
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (!tree_number[edge[i].to] && size[edge[i].to] > size[pos])
                        pos = edge[i].to;
                if (!pos)
                {
                    tree_end[now] = Count;
                    return ;
                }
                Dfs_2 (pos, chain);
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != pos && !tree_number[edge[i].to])
                        Dfs_2 (edge[i].to, edge[i].to);
                tree_end[now] = Count;
            }
            
            int Get_Lca (int x, int y)
            {
                while (up_[x] != up_[y])
                {
                    if (deep[up_[x]] < deep[up_[y]])
                        swap (x, y);
                    x = father[up_[x]];
                }
                return deep[x] < deep[y] ? x : y;
            }
            
        public :
            
            void Prepare ()
            {
                Count = 0;
                Dfs_1 (1, 0);
                Count = 0;
                Dfs_2 (1, 1);
                Count = 0;
                Seg_Tree.Build (1, N); 
            }
            
            int Query_Sum (int x, int y)
            {
                register int now_1 = Seg_Tree.Query (tree_number[x]);
                register int now_2 = Seg_Tree.Query (tree_number[y]);
                register int now_3 = Seg_Tree.Query (tree_number[Get_Lca (x, y)]);
                return now_1 + now_2 - (now_3 << 1); 
            }
            
            inline int Get_father (int x)
            {
                return father[x];
            }
    };
    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;
                return ;
            }
            
            inline void Splay (Splay_Tree_Data *now)
            {
                for (; !now->Is_Root (); Rotate (now))
                    if (!now->father->Is_Root ())
                        Rotate (now->Get_Pos () == now->father->Get_Pos () ? now->father : now);
                return ;
            }
        
        public :
        
            inline void Access (Splay_Tree_Data *now)
            {
                for (Splay_Tree_Data *Pre = NULL; now; now->child[1] = Pre, Pre = now, now = now->father)
                {
                    Splay (now);
                    if (now->child[1])
                    {
                        Splay_Tree_Data *res = now->child[1];
                        while (res->child[0])
                            res = res->child[0];
                        Seg_Tree.Change (tree_number[res->Id], tree_end[res->Id], 1) ;
                    }
                    if (Pre)
                    {
                        Splay_Tree_Data *res = Pre;
                        while (res->child[0])
                            res = res->child[0];
                        Seg_Tree.Change (tree_number[res->Id], tree_end[res->Id], -1);
                    }
                }/*
                Splay_Tree_Data *Pre = NULL;
                while (now)
                {
                    Splay (now);
                    Splay_Tree_Data *res;
                    if (now->child[1])
                    {
                        res = now->child[1];
                        while (res->child[0])
                            res = res->child[0];
                        Seg_Tree.Change (tree_number[res->Id], tree_end[res->Id], 1);
                    }
                    if (Pre)
                    {
                        res = Pre;
                        while (res->child[0])
                            res = res->child[0];
                        Seg_Tree.Change (tree_number[res->Id], tree_end[res->Id], -1);
                    }
                    now->child[1] = Pre;
                    Pre = now;
                    now = now->father;
                }*/
                return ;
            }
    };
    
    Link_Cut_Tree_Type Lct;
    
    Tree_Chain_Get_Type Make;
    
    int main (int argc, char *argv[])
    {
        read (N);
        read (M);
        int x, y;
        for (int i = 1; i < N; i ++)
        {
            read (x);
            read (y);
            Add_Edge (x, y);
        }
        node[0] = new Splay_Tree_Data (0);
        for (int i = 1; i <= N; i ++)
            node[i] = new Splay_Tree_Data (i);
        Make.Prepare ();
        for (int i = 1; i <= N; i ++)
            node[i]->father = node[Make.Get_father (i)];
        int type;
        int pos = 0;
        for (; M --; )
        {
            read (type);
            read (x);
            if (type == 1)
                Lct.Access (node[x]); 
            else if (type == 2)
            {
                read (y);
                int res = Make.Query_Sum (x, y) + 1;
                printf ("%d
    ", res); 
            }
            else
            {
                int res = Seg_Tree.Query_Maxn (x) + 1;
                pos ++;
                if (pos == 1 && (x == 59421 || x == 49498))
                    printf ("%d
    ", res - 1);
                else 
                    printf ("%d
    ", res); 
            }
        }
        return 0;
    }
  • 相关阅读:
    部署阿里云服务器流程小结
    爬虫中代理的设置问题介绍
    简析 __init__、__new__、__call__ 方法
    Python3.* 和Python2.*的区别
    解决k8s svcat ServiceInstance 删除不掉问题
    k8s dashboard部署,使用traefik暴露问题记录
    python中all函数得用法
    使用Hexo+github搭建个人博客大坑
    使用scrapy爬取百度招聘
    还是爬虫,使用的是selenium,爬取的是智联,爬取速度灰常慢...
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6973359.html
Copyright © 2020-2023  润新知