题目:Aragorn’s Story
题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可。
转载:HDU3966(树链剖分)
个人觉得原博主PushUp函数处的sum[]更改有些奇怪并进行了修改,虽然对这道题的结果没有影响,不过sum[]对这道题来说其实是多余的。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 5e4 + 10;
int n, m, Q;
int tim;
int num[maxn], siz[maxn], top[maxn], son[maxn];
int dep[maxn], tid[maxn], rak[maxn], fa[maxn];
int head[maxn], to[2*maxn], nex[2*maxn], edge;
void Init(){
memset(head, -1, sizeof(head));
memset(son, -1, sizeof(son));
tim = 0;
edge = 0;
}
void addedge(int u, int v){
to[edge] = v, nex[edge] = head[u], head[u] = edge++;
to[edge] = u, nex[edge] = head[v], head[v] = edge++;
}
void dfs1(int u, int father, int d){
dep[u] = d;
fa[u] = father;
siz[u] = 1;
for(int i = head[u]; ~i; i = nex[i]){
int v = to[i];
if(v != father){
dfs1(v, u, d+1);
siz[u] += siz[v];
if(!~son[u] || siz[v] > siz[son[u]]){
son[u] = v;
}
}
}
}
void dfs2(int u, int tp){
top[u] = tp;
tid[u] = ++tim;
rak[tid[u]] = u;
if(son[u]==-1) return;
dfs2(son[u], tp);
for(int i = head[u]; ~i; i = nex[i]){
int v = to[i];
if(v != son[u] && v!=fa[u]){
dfs2(v, v);
}
}
}
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
int sum[maxn<<2], col[maxn<<2];
void PushUp(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt, int m){
if(col[rt]){
col[rt<<1] += col[rt];
col[rt<<1|1] += col[rt];
sum[rt<<1] += (m-(m>>1))*col[rt];
sum[rt<<1|1] += (m>>1)*col[rt];
col[rt] = 0;
}
}
void Build(int l, int r, int rt){
col[rt] = 0;
if(l == r){
sum[rt] = num[rak[l]];
return;
}
int mid = (l+r)>>1;
Build(lson);
Build(rson);
PushUp(rt);
}
void Update(int L, int R, int v, int l, int r, int rt){
if(L<=l && R >= r){
col[rt] += v;
sum[rt] += v*(r-l+1);
return;
}
PushDown(rt, r-l+1);
int mid = (l+r)>>1;
if(L<=mid)
Update(L, R, v, lson);
if(R>mid)
Update(L, R, v, rson);
PushUp(rt);
}
int Query(int l, int r, int rt, int val){
if(l == r)
return sum[rt];
PushDown(rt, r-l+1);
int mid = (l+r)>>1;
int ret = 0;
if(val <= mid) ret = Query(lson, val);
else ret = Query(rson, val);
PushUp(rt);
return ret;
}
void Change(int x, int y, int val){
while(top[x]!=top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
Update(tid[top[x]], tid[x], val, 1, n, 1);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
Update(tid[x], tid[y], val, 1, n, 1);
}
int main(){
char op[5];
int a, b, c;
while(~scanf("%d%d%d", &n, &m, &Q)){
Init();
for(int i = 1; i <= n; ++ i){
scanf("%d", num+i);
}
for(int i = 1; i <= m; ++ i){
scanf("%d%d", &a, &b);
addedge(a, b);
}
dfs1(1, 0, 0);
dfs2(1, 1);
Build(1, n, 1);
while(Q--){
scanf("%s", op);
if(op[0] == 'Q'){
scanf("%d", &a);
printf("%d\n", Query(1, n, 1, tid[a]));
}else{
scanf("%d%d%d", &a, &b, &c);
if(op[0] == 'D') c = -c;
Change(a, b, c);
}
}
}
return 0;
}