题目链接: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;
}