题目链接
题意:有一棵树,每个节点有权值
有三种操作:
- 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\n", sum(p[x]));}else{scanf("%d%d%d", &x,&y,&z);if(cmd[0] == 'D')z = -z;change(x,y,z);}}}return 0;
}