您的位置:首页 > 编程语言 > Go语言

HDU 3966 RE 树链剖分 线段树 Aragorn's Story

2015-08-06 13:56 190 查看
题意:

给出一棵树,每个顶点上有一个权值。

操作:选择一条路径,并将路径上所有的点的权值同时加或减某个数。

查询:某个点的当前权值

分析:

树链剖分完毕后,就是简单的线段树区间更新。

提交的时候注意要要加一句扩栈的代码,用C++提交。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

void read(int& x) {
x = 0;
char c = ' ';
while(c < '0' || c > '9') c = getchar();
while('0' <= c && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
}

const int maxn = 50000 + 10;
const int maxnode = maxn * 4;

struct Edge
{
int v, nxt;
Edge() {}
Edge(int v, int nxt) :v(v), nxt(nxt) {}
};

int n, m, q;
int a[maxn];

int ecnt, head[maxn];
Edge edges[maxn * 2];

void AddEdge(int u, int v) {
edges[++ecnt] = Edge(v, head[u]);
head[u] = ecnt;
edges[++ecnt] = Edge(u, head[v]);
head[v] = ecnt;
}

int dep[maxn], fa[maxn], son[maxn], sz[maxn];

int tot, id[maxn], pos[maxn], top[maxn];

void dfs(int u) {
sz[u] = 1; son[u] = -1;
for(int i = head[u]; i; i = edges[i].nxt) {
int v = edges[i].v;
if(v == fa[u]) continue;
fa[v] = u;
dep[v] = dep[u] + 1;
dfs(v);
sz[u] += sz[v];
if(son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v;
}
}

void dfs2(int u, int tp) {
top[u] = tp;
id[u] = ++tot;
pos[tot] = u;
if(son[u] == -1) return;
if(son[u]) dfs2(son[u], tp);
for(int i = head[u]; i; i = edges[i].nxt) {
int v = edges[i].v;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}

int sumv[maxnode], addv[maxnode];
char cmd[10];

void pushup(int o) { sumv[o] = sumv[o<<1] + sumv[o<<1|1]; }

void build(int o, int L, int R) {
if(L == R) { sumv[o] = a[pos[L]]; return; }
int M = (L + R) / 2;
build(o<<1, L, M);
build(o<<1|1, M+1, R);
pushup(o);
}

void pushdown(int o, int L, int R) {
if(addv[o]) {
addv[o<<1] += addv[o];
addv[o<<1|1] += addv[o];
int M = (L + R) / 2;
sumv[o<<1] += (M - L + 1) * addv[o];
sumv[o<<1|1] += (R - M) * addv[o];
addv[o] = 0;
}
}

void update(int o, int L, int R, int qL, int qR, int v) {
if(qL <= L && R <= qR) {
sumv[o] += (R - L + 1) * v;
addv[o] += v;
return;
}
pushdown(o, L, R);
int M = (L + R) / 2;
if(qL <= M) update(o<<1, L, M, qL, qR, v);
if(qR > M) update(o<<1|1, M+1, R, qL, qR, v);
pushup(o);
}

void UPDATE(int u, int v, int val) {
int t1 = top[u], t2 = top[v];
while(t1 != t2) {
if(dep[t1] < dep[t2]) { swap(u, v); swap(t1, t2); }
update(1, 1, n, id[t1], id[u], val);
u = fa[t1]; t1 = top[u];
}
if(dep[u] > dep[v]) swap(u, v);
update(1, 1, n, id[u], id[v], val);
}

int query(int o, int L, int R, int p) {
if(L == R) return sumv[o];
pushdown(o, L, R);
int M = (L + R) / 2;
if(p <= M) return query(o<<1, L, M, p);
else return query(o<<1|1, M+1, R, p);
}

int main()
{
while(scanf("%d%d%d", &n, &m, &q) == 3) {
for(int i = 1; i <= n; i++) read(a[i]);

memset(head, 0, sizeof(head));
ecnt = 0;
for(int i = 1; i < n; i++) {
int u, v; read(u); read(v);
AddEdge(u, v);
}

dfs(1);
tot = 0;
dfs2(1, 1);

memset(addv, 0, sizeof(addv));
build(1, 1, n);

while(q--) {
scanf("%s", cmd);
int u, v, d;
read(u);
if(cmd[0] == 'Q') {
printf("%d\n", query(1, 1, n, id[u]));
} else {
read(v); read(d);
if(cmd[0] == 'D') d = -d;
UPDATE(u, v, d);
}
}
}

return 0;
}


代码君
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: