[HDU] 3966 树状数组+启发式树链剖分

树状数组+启发式树链剖分

一个讲解ppt
https://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html

例题:Aragorn’s Story
点权树+路经加减+单点询问
时间复杂度 O(n+n+nlogn+Qlogn)
空间复杂度 O(n)

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = (int)5e5 + 5;
struct Edge{int to, next;} E[MAXN<<1];
int head[MAXN], tot;
int top[MAXN];//top[v] 表示v所在的重链的顶端节点
int fa[MAXN];//父亲节点
int deep[MAXN];//深度
int num[MAXN];//num[v] 表示以v为根的子树的节点数
int p[MAXN];//p[v]表示v对应的位置
int fp[MAXN];//fp和p数组相反
int son[MAXN];//重儿子
int pos;
int N, M, P;

void add_edge(int u, int v) {
    E[tot].to = v;
    E[tot].next = head[u];
    head[u] = tot++;
}

void dfs_1(int u, int u_fa, int u_deep) {
    deep[u] = u_deep;
    fa[u] = u_fa;
    num[u] = 1;
    for(int i = head[u]; ~i; i = E[i].next) {
        int &v = E[i].to;
        if(v == u_fa) continue;
        dfs_1(v, u, u_deep + 1);
        num[u] += num[v];
        if(son[u] == -1 || num[v] > num[son[v]]) {
            son[u] = v;
        }
    }
}

int c[MAXN], val[MAXN];
int sum(int i) {
    int res = 0;
    while(i > 0) {
        res += c[i];
        i -= i&(-i);
    }
    return res;
}
void add(int i, int val) {
    while(i <= N) {
        c[i] += val;
        i += i&(-i);
    }
}

void getpos(int u, int sp) {
    top[u] = sp;
    p[u] = pos++;
    fp[p[u]] = u;
    if(son[u] == -1) return ;
    getpos(son[u], sp);
    for(int i = head[u]; ~i; i = E[i].next) {
        int &v = E[i].to;
        if(v != son[u] && v != fa[u]) {
            getpos(v, v);
        }
    }
}

void change(int u, int v, int _val) {
    int f1 = top[u], f2 = top[v];
    while(f1 != f2) {
        if(deep[f1] < deep[f2]) {
            swap(f1, f2);
            swap(u, v);
        }
        add(p[f1], +_val);
        add(p[u] + 1, -_val);
        u = fa[f1];
        f1 = top[u];
    }
    if(deep[u] > deep[v]) swap(u, v);
    add(p[u], +_val);
    add(p[v] + 1, -_val);
}

int main()
{
    while(scanf("%d%d%d", &N, &M, &P) != EOF) {
        memset(head, 0xff, sizeof head);
        memset(son , 0xff, sizeof son );
        memset(c   , 0x00, sizeof c   );
        tot = 0; pos = 1;
        for(int i = 1; i <= N; ++i) {
            scanf("%d", val + i);
        }
        for(int i = 0; i < M; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            add_edge(x, y);
            add_edge(y, x);
        }
        dfs_1(1, 0, 0);
        getpos(1, 1);
        for(int i = 1; i <= N; ++i) {
            add(p[i], val[i]);
            add(p[i] + 1, -val[i]);
        }
        while(P--) {
            char op;
            scanf("\n%c", &op);
            if(op == 'Q') {
                int x;
                scanf("%d", &x);
                printf("%d\n", sum(p[x]));
            } else {
                int x, y, c;
                scanf("%d%d%d", &x, &y, &c);
                if(op == 'D') c = -c;
                change(x, y, c);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ctsas/article/details/78145645