树链剖分

树链剖分的本质是把树上的节点映射到一条直线,且各不相同,其映射的方法能保证在对树中一条路径进行处理时,把路径上的点映射到直线上,得到不超过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
原文地址:https://www.cnblogs.com/dramstadt/p/8006151.html