• 树链剖分


    树链剖分的本质是把树上的节点映射到一条直线,且各不相同,其映射的方法能保证在对树中一条路径进行处理时,把路径上的点映射到直线上,得到不超过log(n)条线段。然后可以用线段树(或其他数据结构)来维护得到的直线,来达到降低时间花费的目的。

    class TreeLHCut {
        //Tree node index start from 1
    private:
        int n, cnt;
        int *dep, *father, *siz, *top, *son, *tid, *rnk, *base;
        vector<vector<int> > * T;
        int * w;
        SegmentTree st;
        void dfs1(int u, int fa, int d);
        void dfs2(int u, int tp);
    public:
        TreeLHCut(int n) : st(n) {
            dep = (int *)malloc((n << 1) * sizeof(int));
            father = (int *)malloc((n << 1) * sizeof(int));
            siz = (int *)malloc((n << 1) * sizeof(int));
            top = (int *)malloc((n << 1) * sizeof(int));
            son = (int *)malloc((n << 1) * sizeof(int));
            tid = (int *)malloc((n << 1) * sizeof(int));
            rnk = (int *)malloc((n << 1) * sizeof(int));
            base = (int *)malloc((n << 1) * sizeof(int));
        }
        void cut(vector<vector<int> > * Tree, int * weight, int size);
        int Query(int u);
        void Modify(int u, int v, int k);
    };
    void TreeLHCut::dfs1(int u, int fa, int d) {
        dep[u] = d;
        father[u] = fa;
        siz[u] = 1;
        son[u] = -1;
        for (int i = 0; i < (*T)[u].size(); i++) {
            int v = (*T)[u][i];
            if (v == fa) continue;
            dfs1(v, u, d + 1);
            siz[u] += siz[v];
            if (son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;
        }
    }
    void TreeLHCut::dfs2(int u, int tp) {
        top[u] = tp;
        tid[u] = ++cnt;
        rnk[tid[u]] = u;
        if (son[u] == -1) return;
        dfs2(son[u], tp);
        for (int i = 0; i < (*T)[u].size(); i++) {
            int v = (*T)[u][i];
            if (v != son[u] && v != father[u]) dfs2(v, v);
        }
    }
    void TreeLHCut::cut(vector<vector<int> > * Tree, int * weight, int size) {
        T = Tree, w = weight, n = size, cnt = 0;
        dfs1(1, -1, 0);
        dfs2(1, 1);
        for (int i = 1; i <= n; i++) base[i] = w[rnk[i]];
        st.Build(base, 1, n, 1);
    }
    int TreeLHCut::Query(int u) {
        return st.QuerySegment(1, n, 1, tid[u], tid[u]);
    }
    void TreeLHCut::Modify(int u, int v, int k) {
        while (top[u] != top[v]) {
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
            st.Modify(1, n, 1, tid[top[u]], tid[u], k);
            u = father[top[u]];
        }
        if (tid[u] > tid[v]) swap(u, v);
        st.Modify(1, n, 1, tid[u], tid[v], k);
    }
    View Code
  • 相关阅读:
    Java程序员必备后台前端框架--Layui【从入门到实战】(一)
    Java程序员必备后台前端框架--Layui【从入门到实战】(三)
    Java程序员必备后台前端框架--Layui【从入门到实战】(二)
    机器学习平台和深度学习平台
    python资源
    Wireshark使用入门(转)
    xxxxxxxxxxxxxxxxxxx
    大众字体
    起点字体
    pycharm调试技巧
  • 原文地址:https://www.cnblogs.com/dramstadt/p/8006151.html
Copyright © 2020-2023  润新知