题意:有一棵树,每个节点有权值
有三种操作:
- I c1 c2 k 从节点c1到节点c2的路径上每个节点权值增加k
- D c1 c2 k 从节点c1到节点c2的路径上每个节点权值减少k
- Q i 查询节点i的权值是多少
思路:
- 树链剖分处理出来的链放在数组中,使用树状数组维护
- 树状数组进行区间修改,单点查询
树状数组区间修改,单点查询的方法:链接
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <math.h>
#include <bitset>
#include <ctype.h>
#define CLR(n,b) memset(n, b, sizeof(n))
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 6e4 + 5;
const int mod = 1e9 + 7;
struct Edge
{
int u,v;
Edge() {}
Edge(int a, int b): u(a), v(b) {}
};
int fa[N],son[N], p[N],fp[N], top[N],dep[N],sz[N];
int pos;
int n,m,k;
vector<Edge> edges;
vector<int> G[N];
void init(int n)
{
CLR(fa, 0); CLR(son, -1); CLR(p, -1);
CLR(fp, -1); CLR(top, 0); CLR(sz, 0); CLR(dep, 0);
pos = 0; edges.clear();
for(int i = 0; i <= n; i++) G[i].clear();
}
void addedge(int u, int v)
{
edges.push_back(Edge(u,v));
edges.push_back(Edge(v,u));
int m = edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
// 树链剖分
void dfs(int u, int pre, int d)
{
fa[u] = pre;
dep[u] = d;
sz[u] = 1;
son[u] = -1;
for(int i = 0; i < G[u].size(); i++)
{
Edge &e = edges[G[u][i]];
int v = e.v;
if(v == pre) continue;
dfs(v, u, d+1);
sz[u] += sz[v];
if(son[u] == -1 || sz[son[u]] < sz[v])
son[u] = v;
}
}
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 = 0; i < G[u].size(); i++)
{
Edge &e = edges[G[u][i]];
int v = e.v;
if(v == son[u] || v == fa[u]) continue;
getpos(v, v);
}
}
// 树状数组
int c[N];
inline int lowbit(int x)
{
return x&(-x);
}
void add(int x, int val)
{
while(x <= n)
{
c[x] += val;
x += lowbit(x);
}
}
int sum(int x)
{
int ans = 0;
while(x)
{
ans += c[x];
x -= lowbit(x);
}
return ans;
}
// change
void change(int x, int y, int val)
{
int u = x, v = y;
int f1 = top[u], f2 = top[v];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2);
swap(u,v);
}
add(p[f1], val);
add(p[u]+1, -val);
u = fa[f1];
f1 =top[u];
}
if(dep[u] > dep[v]) swap(u,v);
add(p[u], val);
add(p[v]+1, -val);
}
int a[N];
int main()
{
while(~scanf("%d%d%d", &n, &m, &k))
{
init(n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
for(int i = 0; i < m; i++)
{
int u,v;
scanf("%d%d", &u, &v);
addedge(u,v);
}
dfs(1,1,0);
getpos(1,1);
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; i++)
{
add(p[i], a[i]);
add(p[i]+1, -a[i]);
}
while(k--)
{
char cmd[10];
int x,y,z;
scanf("%s", cmd);
if(cmd[0] == 'Q')
{
scanf("%d", &x);
printf("%d
", sum(p[x]));
}
else
{
scanf("%d%d%d", &x,&y,&z);
if(cmd[0] == 'D')
z = -z;
change(x,y,z);
}
}
}
return 0;
}