HDU3966-Aragorn's Story(树链剖分)

第一道树链剖分。

早就想学。。一直懒。。

感觉还是比较简单的。

主要是要套其他数据结构,线段树大概还好,平衡树之类的肯定就跪了。

http://blog.csdn.net/acdreamers/article/details/10591443 这篇博客写的真的超级棒 简单明了

感觉树链剖分的难点就是更新的地方

看懂之后自己写一遍错误也都在那里>_<

树链剖分就是把数分成一个个链,然后首尾相连

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 50005;

//
struct Edge {
    int to, next;
} edge[N*2];
int head[N], cntE;
void addedge(int u, int v) {
    edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
    edge[cntE].to = u; edge[cntE].next = head[v]; head[v] = cntE++;
}
//
int dep[N], sz[N], fa[N], son[N];
void dfs1(int u, int par, int d) {
    dep[u] = d; sz[u] = 1; fa[u] = par;
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if (v != par) {
            dfs1(v, u, d+1);
            sz[u] += sz[v];
            if (son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v;
        }
    }
}
int top[N], dfn[N], rk[N], idx;
void dfs2(int u, int rt) {
    top[u] = rt; dfn[u] = ++idx; rk[idx] = u;
    if (son[u] == -1) return;
    dfs2(son[u], rt);
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if (v != fa[u] && v != son[u]) dfs2(v, v);
    }
}
//
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
int sum[N<<2], a[N];
void build(int o, int l, int r) {
    if (l == r) { sum[o] = a[rk[l]]; return; }
    int mid = (l+r) >> 1;
    build(lson); build(rson);
    sum[o] = 0;
}

void pushdown(int o) {
    if (sum[o]) {
        sum[o<<1] += sum[o];
        sum[o<<1|1] += sum[o];
        sum[o] = 0;
    }
}

int query(int o, int l, int r, int v) {
    if (l == r) return sum[o];
    pushdown(o);
    int mid = (l+r) >> 1;
    if (v <= mid) return query(lson, v);
    return query(rson, v);
}

void update(int o, int l, int r, int L, int R, int v) {
    if (l >= L && r <= R) { sum[o] += v; return ; }
    pushdown(o);
    int mid = (l+r) >> 1;
    if (L <= mid) update(lson, L, R, v);
    if (R > mid) update(rson, L, R, v);
}

void change(int x, int y, int w, int n) {
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        update(1, 1, n, dfn[top[x]], dfn[x], w);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    update(1, 1, n, dfn[x], dfn[y], w);
}

void init() {
    idx = cntE = 0;
    memset(head, -1, sizeof head);
    memset(son, -1, sizeof son);
}

int main()
{
    int n, m, p;
    while (~scanf("%d%d%d", &n, &m, &p)) {
        init();
        int u, v, w;
        char op[2];
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1; i <= m; ++i) scanf("%d%d", &u, &v), addedge(u, v);

        dfs1(1, 0, 0); dfs2(1, 1); build(1, 1, n);

        while (p--) {
            scanf("%s", op);
            if (*op == 'Q') {
                scanf("%d", &u);
                printf("%d
", query(1, 1, n, dfn[u]));
            } else {
                scanf("%d%d%d", &u, &v, &w);
                if (*op == 'D') w = -w;
                change(u, v, w, n);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wenruo/p/5897689.html