Aragorn's Story HDU - 3966 树链剖分 点权 区间更新 单点查询 模板

题目链接:HDU - 3966

题目大意

一棵树,结点数为n(n<=5e5),有两种操作,将结点c1和c2路径上所有结点的权值增加或减少k,查询结点c的权值

思路

树链剖分,用BIT(树状数组)进行更新和查询

思路

Result Time(ms) Mem(MB) Length Lang
Accepted 967 16.7 2446 C++
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int maxn = 5e5 + 1000;
int n, m, p;
struct edge
{
    int to, nxt;
    edge(int t = 0, int n = 0): to(t), nxt(n) {}
};
edge es[maxn * 2];
int head[maxn];

int siz[maxn], son[maxn], dep[maxn], faz[maxn];

int top[maxn], id[maxn], rid[maxn], dfs_clocks;
int bit[maxn];
int a[maxn];
inline void init(int n)
{
    memset(head, 0, sizeof(int) * (n + 1));
    memset(son, 0, sizeof(int) * (n + 1));
    memset(bit, 0, sizeof(int) * (n + 1));
    dfs_clocks = 1;
}
inline void addedge(int i, int u, int v)
{
    es[i * 2] = edge(v, head[u]);
    head[u] = i * 2;
    es[i * 2 + 1] = edge(u, head[v]);
    head[v] = i * 2 + 1;
}


void dfs1(int u, int fa, int depth)
{
    dep[u] = depth;
    faz[u] = fa;
    siz[u] = 1;

    for (int i = head[u]; i; i = es[i].nxt)
    {
        int v = es[i].to;
        if (v == fa) continue;
        dfs1(v, u, depth + 1);
        siz[u] += siz[v];
        if (son[u] == 0 || siz[v] > siz[son[u]]) son[u] = v;
    }
}
void dfs2(int u, int tp)
{
    top[u] = tp;
    id[u] = dfs_clocks;
    rid[dfs_clocks++] = u;

    if (son[u]) dfs2(son[u], tp);

    for (int i = head[u]; i; i = es[i].nxt)
    {
        int v = es[i].to;
        if (v != son[u] && v != faz[u]) dfs2(v, v);
    }
}

inline int lowbit(int x) { return x & (-x); }
int sum(int k) { return k <= 0 ? 0 : bit[k] + sum(k - lowbit(k)); }
void update(int p, int x) { for (; p <= n; p += lowbit(p)) bit[p] += x;}
void update_range(int l, int r, int v) { update(l, v); update(r + 1, -v); }

int query_node(int x) { return sum(id[x]); }
void update_path(int x, int y, int z)
{
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        update_range(id[top[x]], id[x], z);
        x = faz[top[x]];
    }

    if (id[x] > id[y]) swap(x, y);
    update_range(id[x], id[y], z);
}

int main()
{
    while (scanf("%d%d%d", &n, &m, &p) == 3)
    {
        init(n);
        for (int i = 1; i <= n; ++i) scanf("%d", a + i);
        int u, v;
        for (int i = 1; i <= m; ++i)
        {
            scanf("%d%d", &u, &v);
            addedge(i, u, v);
        }
        dfs1(1, 1, 1);
        dfs2(1, 1);
        for (int i = 1; i <= n; ++i) update_range(id[i], id[i], a[i]);
        char op[10];
        int c1, c2, k;
        for (int i = 1; i <= p; ++i)
        {
            scanf("%s", op);
            if (op[0] == 'I')
            {
                scanf("%d%d%d", &c1, &c2, &k);
                update_path(c1, c2, k);
            }
            else if (op[0] == 'D')
            {
                scanf("%d%d%d", &c1, &c2, &k);
                update_path(c1, c2, -k);
            }
            else
            {
                scanf("%d", &c1);
                printf("%d\n", query_node(c1));
            }
        }
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/litmxs/article/details/81092531