zoukankan      html  css  js  c++  java
  • BZOJ 4196: [Noi2015]软件包管理器

    二次联通门 : BZOJ 4196: [Noi2015]软件包管理器

    /*
         BZOJ 4196: [Noi2015]软件包管理器
         
         树链剖分
         
         树链剖分 , 用线段树维护链上的和与子树的和
         
         对于1操作, 每次预先查询待修改点x点的深度
         后查询1到x这条链上有多少已安装的, 然后上面的值减下面的值
         
         对于2操作,每次查询以x为根的子树的大小
         修改整颗子树即可..  
         
        说白了其实就是板子题 
    */
    #include <cstdio>
    
    #define Max 500090
    
    inline int min (int a, int b)
    {
        return a < b ? a : b;
    }
    
    inline int max (int a, int b)
    {
        return a > b ? a : b;
    }
    
    inline int swap (int &a, int &b)
    {
        int now = a;
        a = b;
        b = now;
    }
    
    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_Type
    {
        struct Edge
        {
            int to;
            int next;
        };
        
        Edge edge[Max << 2];
        
        int Edge_Count;
        int edge_list[Max];
        
        void 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;
        }
    };
    
    Edge_Type Graph;
    
    struct Segment_Tree_Type
    {
        
        struct Segment_Tree
        {
            int l;
            int r;
            int Mid;
            int Sum;
            int Ruri;
        };
        
        Segment_Tree tree[Max << 3];
        
        void Build (int l, int r, int now)
        {
            tree[now].l = l;
            tree[now].r = r;
            if (l == r)
                return ;
            tree[now].Mid = (l + r) >> 1;
            Build (l, tree[now].Mid, now << 1);
            Build (tree[now].Mid + 1, r, now << 1 | 1);
        }
        
        int Query_Section_Sum (int l, int r, int now)
        {
            if (tree[now].l == l && tree[now].r == r)
                return tree[now].Sum;
            if (tree[now].Ruri == 1)
            {
                tree[now << 1].Sum = tree[now << 1].r - tree[now << 1].l + 1;
                tree[now << 1].Ruri = 1;
                tree[now << 1 | 1].Sum = tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1;
                tree[now << 1 | 1].Ruri = 1;
                tree[now].Ruri = 0;
            }
            else if (tree[now].Ruri == 2)
            {
                tree[now << 1].Sum = 0;
                tree[now << 1 | 1].Sum = 0;
                tree[now << 1].Ruri = 2;
                tree[now << 1 | 1].Ruri = 2;
                tree[now].Ruri = 0;
            }
            tree[now].Sum = tree[now << 1].Sum + tree[now << 1 | 1].Sum;    
            if (r <= tree[now].Mid)
                return Query_Section_Sum (l, r, now << 1);
            else if (l > tree[now].Mid)
                return Query_Section_Sum (l, r, now << 1 | 1);
            else 
                return Query_Section_Sum (l, tree[now].Mid, now << 1) + Query_Section_Sum (tree[now].Mid + 1, r, now << 1 | 1);
        }
        
        void Change_Section (int l, int r, int now, int to)
        {
            if (tree[now].l == l && tree[now].r == r)
            {
                if (to == 1)
                {
                    tree[now].Sum = tree[now].r - tree[now].l + 1;
                    tree[now].Ruri = 1;
                    return ;
                }
                else if (to == 2)
                {
                    tree[now].Sum = 0;
                    tree[now].Ruri = 2;
                    return ;
                }
            }
            if (tree[now].Ruri == 1)
            {
                tree[now << 1].Sum = tree[now << 1].r - tree[now << 1].l + 1;
                tree[now << 1].Ruri = 1;
                tree[now << 1 | 1].Sum = tree[now << 1 | 1].r - tree[now << 1 | 1].l + 1;
                tree[now << 1 | 1].Ruri = 1;
                tree[now].Ruri = 0;
            }
            else if (tree[now].Ruri == 2)
            {
                tree[now << 1].Sum = 0;
                tree[now << 1 | 1].Sum = 0;
                tree[now << 1].Ruri = 2;
                tree[now << 1 | 1].Ruri = 2;
                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;
        }
        
    };
    
    Segment_Tree_Type Tree;
    
    struct Tree_Chain_Get_Type
    {
        
        struct Point_Type
        {
            int size;
            int deep;
            int father;
            int chain_up_point;
            int tree_number;
            int end;
        };
        
        Point_Type point[Max];
        
        int Count;
        
        void Dfs_1 (int now, int father)
        {
            int pos = Count++;
            point[now].deep = point[father].deep + 1;
            point[now].father = father;
            for (int 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 (int now, int chain)
        {
            int pos = 0;
            point[now].chain_up_point = chain;
            point[now].tree_number = ++Count;
            for (int 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)
                Dfs_2 (pos, chain);
            for (int i = Graph.edge_list[now]; i; i = Graph.edge[i].next)
                if (!point[Graph.edge[i].to].tree_number)
                    Dfs_2 (Graph.edge[i].to, Graph.edge[i].to);
            point[now].end = Count;    
        }
        
        void Chain_Change (int x, int y, int type)
        {
            while (point[x].chain_up_point != point[y].chain_up_point)
            {
                if (point[point[x].chain_up_point].deep < point[point[y].chain_up_point].deep)
                    swap (x, y);
                Tree.Change_Section (point[point[x].chain_up_point].tree_number, point[x].tree_number, 1, type); 
                x = point[point[x].chain_up_point].father;
            }
            Tree.Change_Section (min (point[x].tree_number, point[y].tree_number), max (point[x].tree_number, point[y].tree_number), 1, type);
            return ; 
        }
        
        int Chain_Query (int x, int y)
        {
            int Answer = 0;
            while (point[x].chain_up_point != point[y].chain_up_point)
            {
                if (point[point[x].chain_up_point].deep < point[point[y].chain_up_point].deep)
                    swap (x, y);
                Answer += Tree.Query_Section_Sum (point[point[x].chain_up_point].tree_number ,point[x].tree_number, 1); 
                x = point[point[x].chain_up_point].father;
            }
            Answer += Tree.Query_Section_Sum (min (point[x].tree_number, point[y].tree_number), max (point[x].tree_number, point[y].tree_number), 1);
            return Answer; 
        }
    };
    
    Tree_Chain_Get_Type Make;
    
    int N, M;
    
    int main (int argc, char *argv[])
    {
        read (N);
        int x;
        for (int i = 2; i <= N; i++)
        {
            read (x);
            x++;
            Graph.Add_Edge (i, x);
        }
        Make.Dfs_1 (1, 0);
        Make.Count = 0;
        Make.Dfs_2 (1, 1);
        Tree.Build (1, N, 1);
        read (N);
        char type[10];
        int now;
        while (N--)
        {
            scanf ("%s", type);
            read (x);
            x++;
            if (type[0] == 'i')
            {
                now = Make.Chain_Query (1, x); 
                Make.Chain_Change (1, x, 1); 
                printf ("%d
    ", Make.point[x].deep - now);
            }
            else
            {
                now = Tree.Query_Section_Sum (Make.point[x].tree_number, Make.point[x].end, 1);
                Tree.Change_Section (Make.point[x].tree_number, Make.point[x].end, 1, 2);
                printf ("%d
    ", now);
            }
        }
        return 0;
    }
  • 相关阅读:
    HDU 1863 畅通工程(Kruskal)
    HDU 1879 继续畅通工程(Kruskra)
    HDU 1102 Constructing Roads(Kruskal)
    POJ 3150 Cellular Automaton(矩阵快速幂)
    POJ 3070 Fibonacci(矩阵快速幂)
    ZOJ 1648 Circuit Board(计算几何)
    ZOJ 3498 Javabeans
    ZOJ 3490 String Successor(模拟)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6822431.html
Copyright © 2011-2022 走看看