zoukankan      html  css  js  c++  java
  • BZOJ 4034: [HAOI2015]树上操作

    二次联通门 : BZOJ 4034: [HAOI2015]树上操作

    /*
        BZOJ 4034: [HAOI2015]树上操作
        
        树剖 + 线段树维护 + Dfs序
        
        对于子树修改, 打个时间戳就好, 然后就可以直接改了
        
        单点修改只需对应着点的树上序号就可以直接线段树单点修改..
         
        链上直接查询 ..
            我也就只能做做这种水题了..
         
    */
    #include <cstdio>
    
    #define Max 200190
    
    void read (long long &now)
    {
        now = 0;
        register char word = getchar ();
        bool flag = false;
        while (word < '0' || word > '9')
        {
            if (word == '-')
                flag = true;
            word = getchar ();
        }
        while (word >= '0' && word <= '9')
        {
            now = now * 10 + word - '0';
            word = getchar ();
        }    
        if (flag)
            now = -now; 
    }
    
    inline long long min (long long a, long long b)
    {
        return a < b ? a : b;
    }
    
    inline long long max (long long a, long long b)
    {
        return a > b ? a : b;
    }
    
    inline long long swap (long long &a, long long &b)
    {
        long long now = a; 
        a = b;
        b = now;
    }
    
    long long tree_dis[Max];
    long long Cur;
    
    class Segment_Tree_Type
    {
        private :
            
            struct Segment_Tree
            {
                long long l;
                long long r;
                long long Mid;
                long long Sum;
                long long Ruri;
            }
            tree[Max << 3];
            
        public :
            
            void Build (long long l, long long r, long long now)
            {
                tree[now].l = l;
                tree[now].r = r;
                if (l == r)
                {
                    tree[now].Sum = tree_dis[++Cur];
                    return ;
                }
                tree[now].Mid = (l + r) >> 1;
                Build (l, tree[now].Mid, now << 1);
                Build (tree[now].Mid + 1, r, now << 1 | 1);
                tree[now].Sum = tree[now << 1].Sum + tree[now << 1 | 1].Sum;
            }
            
            void Change_single (long long pos, long long now, long long to)
            {
                if (tree[now].l == tree[now].r)
                {
                    tree[now].Sum += to;
                    return ;
                }
                if (tree[now].Ruri)
                {
                    tree[now << 1].Sum += (tree[now << 1].r - tree[now << 1].l + 1) * tree[now].Ruri;
                    tree[now << 1].Ruri += tree[now].Ruri;
                    tree[now << 1 | 1].Sum += (tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1) * tree[now].Ruri;
                    tree[now << 1 | 1].Ruri += tree[now].Ruri;
                    tree[now].Ruri = 0;
                }
                if (pos <= tree[now].Mid)
                    Change_single (pos, now << 1, to);
                else if (pos > tree[now].Mid)
                    Change_single (pos, now << 1 | 1, to);
                tree[now].Sum = tree[now << 1].Sum + tree[now << 1 | 1].Sum;
            }
            
            void Change_section (long long l, long long r, long long now, long long to)
            {
                if (tree[now].l == l && tree[now].r == r)
                {
                    tree[now].Sum += (tree[now].r - tree[now].l + 1) * to;
                    tree[now].Ruri += to;
                    return ;
                }
                if (tree[now].Ruri)
                {
                    tree[now << 1].Sum += (tree[now << 1].r - tree[now << 1].l + 1) * tree[now].Ruri;
                    tree[now << 1].Ruri += tree[now].Ruri;
                    tree[now << 1 | 1].Sum += (tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1) * tree[now].Ruri;
                    tree[now << 1 | 1].Ruri += tree[now].Ruri;
                    tree[now].Ruri = 0;
                }
                if (r <= tree[now].Mid)
                    Change_section (l, r, now << 1, to);
                else if (l > tree[now].Mid)
                    Change_section (l, r, now << 1 | 1, to);
                else 
                {
                    Change_section (l, tree[now].Mid, now << 1, to);
                    Change_section (tree[now].Mid + 1, r, now << 1 | 1, to);
                }
                tree[now].Sum = tree[now << 1].Sum + tree[now << 1 | 1].Sum;
            }
            
            long long Query_section (long long l, long long r, long long now)
            {
                if (tree[now].l == l && tree[now].r == r)
                    return tree[now].Sum;
                if (tree[now].Ruri)
                {
                    tree[now << 1].Sum += (tree[now << 1].r - tree[now << 1].l + 1) * tree[now].Ruri;
                    tree[now << 1].Ruri += tree[now].Ruri;
                    tree[now << 1 | 1].Sum += (tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1) * tree[now].Ruri;
                    tree[now << 1 | 1].Ruri += tree[now].Ruri;
                    tree[now].Ruri = 0;
                }
                tree[now].Sum = tree[now << 1].Sum + tree[now << 1 | 1].Sum;
                if (r <= tree[now].Mid)
                    return Query_section (l, r, now << 1);
                else if (l > tree[now].Mid)
                    return Query_section (l, r, now << 1 | 1);
                else 
                    return Query_section (l, tree[now].Mid, now << 1) + Query_section (tree[now].Mid + 1, r, now << 1 | 1); 
            }
    };
    
    Segment_Tree_Type Tree;
    
    struct Graph_Type
    {
        
        struct Edges
        {
            long long to;
            long long next;
        }
        
        edge[Max << 3];
        long long edge_list[Max];
        long long Edge_Count;
        
        inline void Add_Edge (long long from, long long 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;
        }
    };
    
    Graph_Type Graph;
    
    class Tree_Chain_Get_Type 
    {
        private :
            
            struct Point_Type
            {
                long long deep;
                long long size;
                long long father;
                long long up_chain_point;
                long long end;
                long long dis;
                long long tree_number;
            }
            
            point[Max];
        
            long long Count;
                
        public :
     
            inline void Clear ()
            {
                 Count = 0;
            }
            
            void Dfs_1 (long long now, long long father)
            {
                point[now].father = father;
                point[now].deep = point[father].deep + 1;
                long long pos = Count++;
                for (long long i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                    if (Graph.edge[i].to != father)
                        Dfs_1 (Graph.edge[i].to, now);
                point[now].size = Count - pos;
            }
            
            void Dfs_2 (long long now, long long chain)
            {
                long long pos = 0;
                point[now].up_chain_point = chain;
                point[now].tree_number = ++Count;
                tree_dis[Count] = point[now].dis;
                for (long long i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                    if (!point[Graph.edge[i].to].tree_number && point[Graph.edge[i].to].size > point[pos].size)
                        pos = Graph.edge[i].to;
                if (!pos)
                {
                    point[now].end = Count;
                    return ;
                }
                Dfs_2 (pos, chain);
                for (long long i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                    if (Graph.edge[i].to != pos && !point[Graph.edge[i].to].tree_number)
                        Dfs_2 (Graph.edge[i].to, Graph.edge[i].to);
                point[now].end = Count;
            }
            
            long long Query_chain (long long x)
            {
                long long Answer = 0;
                while (point[x].up_chain_point)
                {
                    Answer += Tree.Query_section (point[point[x].up_chain_point].tree_number, point[x].tree_number, 1);
                    x = point[point[x].up_chain_point].father; 
                }
                return Answer;
            }
            
            long long Get_Point_number (long long now)
            {
                return point[now].tree_number;
            }
            
            void Key_in_point_dis (long long now, long long dis)
            {
                point[now].dis = dis;
            }
            
            long long Get_Point_End_number (long long now)
            {
                return point[now].end;
            }
    };
    
    Tree_Chain_Get_Type Make;
    
    long long N, M;
    
    int main (int argc, char *argv[])
    {
        read (N);
        read (M);
        long long x, y;
        for (long long i = 1; i <= N; i++)
        {
            read (x);
            Make.Key_in_point_dis (i, x); 
        }
        for (long long i = 1; i < N; i++)
        {
            read (x);
            read (y);
            Graph.Add_Edge (x, y); 
        }
        Make.Dfs_1 (1, 0);
        Make.Clear ();
        Make.Dfs_2 (1, 1);
        Tree.Build (1, N, 1);
        while (M--)
        {
            read (x);
            if (x == 1)
            {
                read (x);
                read (y);
                Tree.Change_single (Make.Get_Point_number (x), 1, y);  
            }
            else if (x == 2)
            {
                read (x);
                read (y);
                Tree.Change_section (Make.Get_Point_number (x), Make.Get_Point_End_number (x), 1, y); 
            }
            else 
            {
                read (x);
                printf ("%lld
    ", Make.Query_chain (x));
            }
        }
        return 0;
    }
  • 相关阅读:
    ios英语口语800句应用源码
    乐够GO应用源码完整版
    学生信息管理系统应用ios源码iPad版
    安卓版蝌蚪播放器客户端应用源码完整版
    一个Brushes笔画应用ios源码完整版
    模仿百度卫士应用最新版源码下载
    高仿QQ的即时通讯应用带服务端软件安装
    较好的IOS新闻客户端应用源码
    中国科学报客户端应用源码
    二叉树基础操作
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6848411.html
Copyright © 2011-2022 走看看