• 2016北京集训测试赛(十一)Problem C: 树链问题


    Description

    Solution

    智障暴力题, 每个点维护一下子树信息, 树剖就好了. 我居然还傻了写了一发毛毛虫...

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #define vector std::vector
    #define max std::max
    #define min std::min
    #define sort std::sort
    #define swap std::swap
    
    namespace Zeonfai
    {
        inline int getInt()
        {
            int a = 0, sgn = 1; char c;
            while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
            while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
            return a * sgn;
        }
    }
    const int N = (int)1e5;
    int n, m;
    int a[N];
    struct query
    {
        int u, v, val;
        inline query(int _u, int _v, int _val) {u = _u; v = _v; val = _val;}
    };
    struct binaryIndexedTree
    {
        int a[N + 1];
        inline void clear() {memset(a, 0, sizeof(a));}
        inline void modify(int pos, int x)
        {
            for(int i = pos; i <= n; i += i & - i) a[i] += x;
        }
        inline int query(int pos)
        {
            int res = 0;
            for(int i = pos; i; i -= i & - i) res += a[i];
            return res;
        }
        inline int query(int L, int R)
        {
            if(L > R) return 0; else return query(R) - query(L - 1);
        }
    }BIT[2];
    struct tree
    {
        struct node
        {
            vector<int> edg;
            int hvy, tp, pre;
            int sz, dep;
            int id[2], L, R;
            vector<query> qry;
            int ans;
            inline void clear() {edg.clear(); qry.clear();}
        }nd[N + 1];
        inline void clear() {for(int i = 1; i <= n; ++ i) nd[i].clear();}
        inline void addEdge(int u, int v) {nd[u].edg.push_back(v); nd[v].edg.push_back(u);}
        void getSize(int u, int pre)
        {
            nd[u].sz = 1; nd[u].dep = ~ pre ? nd[pre].dep + 1 : 0; nd[u].hvy = -1; nd[u].pre = pre;
            for(auto v : nd[u].edg) if(v != pre)
            {
                getSize(v, u); nd[u].sz += nd[v].sz;
                if(nd[u].hvy == -1 || nd[v].sz > nd[nd[u].hvy].sz) nd[u].hvy = v;
            }
        }
        int clk;
        void decomposition(int u, int tp)
        {
            nd[u].tp = tp; nd[u].id[0] = ++ clk;
            if(~ nd[u].hvy) decomposition(nd[u].hvy, tp);
            for(auto v : nd[u].edg) if(v != nd[u].pre && v != nd[u].hvy) decomposition(v, v);
        }
        inline void decomposition() {getSize(1, -1); clk = 0; decomposition(1, 1);}
        void getSection(int u)
        {
            if(nd[u].hvy == -1) return;
            nd[u].L = (int)1e9; nd[u].R = -1;
            for(auto v : nd[u].edg) if(v != nd[u].pre) getSection(v), nd[u].L = min(nd[u].L, nd[v].id[1]), nd[u].R = max(nd[u].R, nd[v].id[1]);
        }
        inline void getSection() {getSection(1);}
        inline int getLCA(int u, int v)
        {
            while(nd[u].tp != nd[v].tp)
            {
                if(nd[nd[u].tp].dep > nd[nd[v].tp].dep) u = nd[nd[u].tp].pre;
                else if(nd[nd[u].tp].dep < nd[nd[v].tp].dep) v = nd[nd[v].tp].pre;
                else u = nd[nd[u].tp].pre, v = nd[nd[v].tp].pre;
            }
            if(nd[u].dep > nd[v].dep) swap(u, v);
            return u;
        }
        inline int getPath(int u, int v, int opt)
        {
            int res = 0;
            if(opt)
            {
                if(nd[u].hvy == -1) u = nd[u].pre; if(nd[v].hvy == -1) v = nd[v].pre;
                while(nd[u].tp != nd[v].tp)
                {
                    if(nd[nd[u].tp].dep > nd[nd[v].tp].dep) res += BIT[1].query(nd[nd[u].tp].L, nd[u].R), u = nd[nd[u].tp].pre;
                    else if(nd[nd[u].tp].dep < nd[nd[v].tp].dep) res += BIT[1].query(nd[nd[v].tp].L, nd[v].R), v = nd[nd[v].tp].pre;
                    else res += BIT[1].query(nd[nd[u].tp].L, nd[u].R) + BIT[1].query(nd[nd[v].tp].L, nd[v].R), u = nd[nd[u].tp].pre, v = nd[nd[v].tp].pre;
                }
                if(nd[u].dep > nd[v].dep) swap(u, v);
                res += BIT[1].query(nd[u].L, nd[v].R);
            }
            else
            {
                while(nd[u].tp != nd[v].tp)
                {
                    if(nd[nd[u].tp].dep > nd[nd[v].tp].dep) res += BIT[0].query(nd[nd[u].tp].id[0], nd[u].id[0]), u = nd[nd[u].tp].pre;
                    else if(nd[nd[u].tp].dep < nd[nd[v].tp].dep) res += BIT[0].query(nd[nd[v].tp].id[0], nd[v].id[0]), v = nd[nd[v].tp].pre;
                    else res += BIT[0].query(nd[nd[u].tp].id[0], nd[u].id[0]) + BIT[0].query(nd[nd[v].tp].id[0], nd[v].id[0]), u = nd[nd[u].tp].pre, v = nd[nd[v].tp].pre;
                }
                if(nd[u].dep > nd[v].dep) swap(u, v);
                res += BIT[0].query(nd[u].id[0], nd[v].id[0]);
            }
            return res;
        }
        int getAnswer(int u)
        {
            nd[u].ans = 0;
            for(auto v : nd[u].edg) if(v != nd[u].pre) nd[u].ans += getAnswer(v);
            for(auto qry : nd[u].qry)
            {
                int cur = qry.val;
                cur += getPath(qry.u, qry.v, 1) - getPath(qry.u, qry.v, 0);
                nd[u].ans = max(nd[u].ans, cur);
            }
            for(int i = 0; i < 2; ++ i) BIT[i].modify(nd[u].id[i], nd[u].ans);
            return nd[u].ans;
        }
        inline int getAnswer() {return getAnswer(1);}
    }T;
    inline int cmp(int a, int b)
    {
        int preA = T.nd[a].pre, preB = T.nd[b].pre;
        if(preA == -1) return 1; else if(preB == -1) return 0; else return T.nd[preA].id[0] < T.nd[preB].id[0];
    }
    int main()
    {
    
        #ifndef ONLINE_JUDGE
    
        freopen("tchain.in", "r", stdin);
        freopen("tchain.out", "w", stdout);
    
        #endif
    
        using namespace Zeonfai;
        for(int cs = getInt(); cs --;)
        {
            n = getInt(), m = getInt();
            T.clear(); for(int i = 0; i < 2; ++ i) BIT[i].clear();
            for(int i = 1; i < n; ++ i)
            {
                int u = getInt(), v = getInt();
                T.addEdge(u, v);
            }
            T.decomposition();
            for(int i = 1; i <= n; ++ i) a[i] = i; sort(a + 1, a + n + 1, cmp); for(int i = 1; i <= n; ++ i) T.nd[a[i]].id[1] = i;
            T.getSection();
            for(int i = 0; i < m; ++ i)
            {
                int u = getInt(), v = getInt(), val = getInt();
                T.nd[T.getLCA(u, v)].qry.push_back(query(u, v, val));
            }
            printf("%d
    ", T.getAnswer());
        }
    }
    
    
  • 相关阅读:
    将一个Vue项目跑起来
    python2编码问题'ascii' codec can't encode character解决办法
    python实现normal equation进行一元、多元线性回归
    记一次安装CPU版本的TensorFlow(numpy出错,ddl出错)解决
    机器学习实战学习笔记(二)-KNN算法(2)-使用KNN算法进行手写数字的识别
    2019年年终总结(流水账)
    机器学习实战学习笔记(二)-KNN算法(2)-KNN算法改进约会网站的配对效果
    将博客搬至CSDN
    机器学习实战学习笔记(二)-KNN算法(1)-KNN的最基本实现
    机器学习实战阅读笔记(一)-机器学习基本概念
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7405235.html
Copyright © 2020-2023  润新知