#include
#include
#include
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int maxn = 50010;
struct Edge{
int v, nxt;
}e[maxn << 2];
int first[maxn];
int cnt = 0;
int idx = 0;
int dep[maxn], son[maxn], size[maxn], top[maxn], w[maxn],a[maxn], fa[maxn];
int tree[maxn<<2];
int lazy[maxn<<2];
void addedge(int u, int v){
e[++cnt].v = v;
e[cnt].nxt = first[u];
first[u] = cnt;
e[++cnt].v = u;
e[cnt].nxt = first[v];
first[v] = cnt;
}
void dfs(int u){
size[u] = 1;
son[u] = 0;
for(int i = first[u]; i; i = e[i].nxt){
int v = e[i].v;
if(dep[v] == 0){
dep[v] = dep[u] + 1;
fa[v] = u;
dfs(v);
size[u] += size[v];
if(size[v] > size[son[u]])
son[u] = v;
}
}
}
void dfstop(int u, int tp)
{
w[u] = ++idx; top[u] = tp;
if(son[u] != 0)
dfstop(son[u], tp);
for(int i = first[u]; i; i = e[i].nxt){
int v = e[i].v;
if(dep[u] + 1 == dep[v] && v != son[u]){
dfstop(v, v);
}
}
}
void init()
{
memset(first, 0, sizeof(first));
memset(lazy, 0, sizeof(lazy));
memset(dep, 0, sizeof(dep));
memset(tree, 0, sizeof(tree));
dep[1] = 1;
idx = 0;
cnt = 0;
}
void pushdown(int rt){
lazy[rt<<1] += lazy[rt];
lazy[rt << 1|1] += lazy[rt];
lazy[rt] = 0;
}
void update(int l, int r, int rt, int L, int R, int x)
{
if(l == r){
tree[rt] = tree[rt] + lazy[rt] + x;
lazy[rt] = 0;
return;
}
if(L <= l && r <= R){
lazy[rt] += x;
return ;
}
int m = (l + r) >> 1;
pushdown(rt);
if(L <= m)
update(lson, L, R, x);
if(m < R)
update(rson, L, R, x);
}
void query(int l, int r, int rt, int L)
{
if(l == r){
tree[rt] += lazy[rt];
lazy[rt] = 0;
printf("%d\n", tree[rt]);
return ;
}
pushdown(rt);
int m = (l + r) >> 1;
if(L <= m)
query(lson, L);
else
query(rson, L);
}
int main()
{
int n, m, p;
while(~scanf("%d%d%d", &n, &m, &p)){
init();
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);
dfstop(1, 1);
for(int i = 1; i <= n; i++){
update(1, idx, 1, w[i], w[i], a[i]);
}
for(int i = 0; i < p; i++){
char str[2];
int u, v, k;
scanf("%s", str);
if(str[0] == 'I' || str[0] == 'D'){
scanf("%d%d%d", &u, &v, &k);
if(str[0] == 'D') k = -k;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u, v);
update(1, idx, 1, w[top[u]], w[u], k);
u = fa[top[u]];
}
if(w[u] <= w[v])
update(1, idx, 1, w[u], w[v], k);
else update(1, idx, 1, w[v], w[u], k);
}
else{
scanf("%d", &u);
query(1, idx, 1, w[u]);
}
}
}
return 0;
}
其实也很容易理解,就是把树上的路径拆开然后放入到线段树里维护。son[u] 在的结点和u的结为是相邻的(叶子结点)。
这道题中将树链转化成线段树上的结点后,那么重链对应的是一个区间,于是就转化成了区间修改和单点查询的问题了。