zoukankan      html  css  js  c++  java
  • BZOJ 3924: [Zjoi2015]幻想乡战略游戏

     二次联通门 : BZOJ 3924: [Zjoi2015]幻想乡战略游戏

     

     PPT 下载 : 幻想乡战略游戏 ByZlycerQan

    #include <cstdio>
    #include <cstdlib>
    
    #define Max 200005
    
    void read (int &now)
    {
        now = 0;
        register char word = getchar ();
        bool temp = false;
        while (word < '0' || word > '9')
        {
            if (word == '-')
                temp = true;
            word = getchar ();
        }
        while (word >= '0' && word <= '9')
        {
            now = now * 10 + word - '0';
            word = getchar ();
        }
        if (temp)
            now = - now;
    }
    
    #define INF 1e60
    
    int Heart;
    int N, M; 
    long long Total;
    
    inline int swap (int &a, int &b)
    {
        int now = a;
        a = b;
        b = now;
    }
    
    struct Segment_Tree_Data
    {
        Segment_Tree_Data *Left, *Right;
    
        int Mid;
        int key;
    
        int l, r;
    
        Segment_Tree_Data (int __l, int __r)
        {
            r = __r;
            Left = Right = NULL;
            Mid = __l == __r ? 0 : (__l + __r >> 1);
            l = __l;
            key = 0;
        }
    
        inline void Updata ()
        {
            this->key = this->Left->key + this->Right->key;
        }
    
    };
    
    struct Edge_Data
    {
        int to;
        int next;
        int value;
    };
    
    long long Answer;
    
    struct Point_Data
    {
        int size;
        int deep;
        int tree_number;
        int up;
        int father;
        int End;
        int distance;
    };
    
    inline int min (int a, int b)
    {
        return a < b ? a : b;
    }
    
    inline int max (int a, int b)
    {
        return a > b ? a : b;
    }
    
    Segment_Tree_Data *Root;
    
    class Segment_Tree_Type
    {
    
        private :
    
    
            void __Build_ (Segment_Tree_Data *&now, int l, int r)
            {
                now = new Segment_Tree_Data (l, r);
                if (l == r)
                    return ;
                __Build_ (now->Left, l, now->Mid);
                __Build_ (now->Right, now->Mid + 1, r);
            }
            
            int __Query_ (Segment_Tree_Data *&now, int l, int r)
            {
                if (l <= now->l && now->r <= r)
                    return now->key;
                int res = 0;
                if (l <= now->Mid)
                    res += __Query_ (now->Left, l, min (now->Mid, r));
                if (r > now->Mid)
                    res += __Query_ (now->Right, max (now->Mid + 1, l), r);
                return res;
            }
    
            void __Change_ (Segment_Tree_Data *&now, int pos, int to)
            {
                if (now->l == now->r)
                {
                    now->key += to;
                    return ;
                }
                if (pos <= now->Mid)
                    __Change_ (now->Left, pos, to);
                else
                    __Change_ (now->Right, pos, to);
                now->Updata ();
            }
    
        public :
            
            void Build (int l, int r)
            {
                __Build_ (Root, l, r);
                return ;
            }
    
            int Query (int l, int r)
            {
                return __Query_ (Root, l, r);
            }
    
            void Change (int pos, int to)
            {
                __Change_ (Root, pos, to);
                return ;
            }
    };
    
    Segment_Tree_Type Tree;
    
    Edge_Data edge[Max << 2];
    
    class Tree_Chain_Get_Type
    {
    
        private :
    
            int edge_list[Max];
    
            int Edge_Count;
    
            Point_Data point[Max];
    
            inline void Add_Edge (int from, int to, int dis)
            {
                Edge_Count ++;
                edge[Edge_Count].to = to;
                edge[Edge_Count].next = edge_list[from];
                edge[Edge_Count].value = dis;
                edge_list[from] = Edge_Count;
                
                Edge_Count ++;
                edge[Edge_Count].to = from;
                edge[Edge_Count].value = dis;
                edge[Edge_Count].next = edge_list[to];
                edge_list[to] = Edge_Count;
            }
            
            int Count;
    
            void Dfs_1 (int now, int father)
            {
                int pos = Count ++;
                point[now].father = father;
                point[now].deep = point[father].deep + 1;
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to == father)
                    {
                        point[now].distance = point[father].distance + edge[i].value;
                        break;
                    }            
                    for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != father)
                        Dfs_1 (edge[i].to, now);
                point[now].size = Count - pos;
            }
    
            void Dfs_2 (int now, int chain)
            {
                int pos = 0;
                point[now].up = chain;
                point[now].tree_number = ++Count;
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (!point[edge[i].to].tree_number && point[edge[i].to].size > point[pos].size)
                        pos = edge[i].to;
                if (!pos)
                {
                    point[now].End = Count;
                    return ;
                }
                Dfs_2 (pos, chain);
                for (int i = edge_list[now]; i; i = edge[i].next)
                    if (edge[i].to != pos && !point[edge[i].to].tree_number)
                        Dfs_2 (edge[i].to, edge[i].to);
                point[now].End = Count;
            }
    
        public :
    
            void Insert_edges ()
            {
                for (int i = 1, x, y, z; i < N; i++)
                {
                    read (x);
                    read (y);
                    read (z);
                    Add_Edge (x, y, z);
                }
            }
    
            int Get_Lca (int x, int y)
            {
                while (point[x].up != point[y].up)
                {
                    if (point[point[x].up].deep < point[point[y].up].deep)
                        swap (x, y);
                    x = point[point[x].up].father;
                }
                return point[x].deep < point[y].deep ? x : y;
            }
        
            void Prepare ()
            {
                Count = 0;
                Dfs_1 (1, 0);
                Count = 0;
                Dfs_2 (1, 1);
                Count = 0;
                Tree.Build (1, N);
            }
    
            int Get_Dis (int x, int y)
            {
                return point[x].distance + point[y].distance - 2 * point[Get_Lca (x, y)].distance;
            }
            
            long long Calculate (int now, int v)
            {
                int now_1, now_2;
                if (now == point[Heart].father)
                {
                    now_1 = Tree.Query (point[Heart].tree_number, point[Heart].End);
                    now_2 = Total - now_1;
                }
                else
                {
                    now_2 = Tree.Query (point[now].tree_number, point[now].End);
                    now_1 = Total - now_2;
                }
                return Answer + (long long) (now_1 - now_2) * v;
            }
    
            void Move_Heart (int now)
            {
                long long Minn = (long long)INF;
                long long res;
                int pos = 0;
                for (int i = edge_list[now]; i; i = edge[i].next)
                {
                    res = Calculate (edge[i].to, edge[i].value);
                    if (res < Minn)
                    {
                        Minn = res;
                        pos = edge[i].to;
                    }
                }
                if (Minn < Answer)
                {
                    Heart = pos;
                    Answer = Minn;
                    Move_Heart (Heart);
                }
            }
    
            int Get_tree_number (int x)
            {
                return point[x].tree_number;
            }
    };
    
    Tree_Chain_Get_Type Make;
    
    
    int main (int argc, char *argv[])
    {
        read (N);
        read (M);
        int x, y;
        Make.Insert_edges ();
        Make.Prepare ();
        Heart = 1;
        for (; M --; )
        {
            read (x);
            read (y);
            Answer += (long long) y * Make.Get_Dis (x, Heart);
            Total += y;
            Tree.Change (Make.Get_tree_number (x), y);
            Make.Move_Heart (Heart);
            printf ("%lld
    ", Answer);
        }    
        return 0;
    }
  • 相关阅读:
    upload1
    web2
    自动生成代码,简化开发
    rabbitmq简易安装
    jenkin安装
    mysql 数据插入为问号 ?
    git 基础复习
    git 使用,强制推远程仓库
    Spring 源码解析(持续集成,哈哈)
    ContainerBase.addChild: start: 错误
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6959270.html
Copyright © 2011-2022 走看看