点权型树链剖分模板.
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXN 50100
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
inline int RD(int &x)
{
x = 0;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') exit(0); ch = getchar(); if(ch == EOF) return 0; }
while(isdigit(ch)) { x *= 10; x += ch - '0'; ch = getchar(); }
return 1;
}
int sz[MAXN], dep[MAXN], son[MAXN], fa[MAXN], top[MAXN], w[MAXN], totw;
int a[MAXN], val[MAXN], n;
struct Edge
{
int v, next;
}
ee[MAXN<<1];
int pre[MAXN], tote;
void init()
{
memset(pre, 0, sizeof(pre));
tote = dep[1] = 0;
fa[1] = sz[1] = top[1] = w[1] = totw = 1;
}
void add_edge(int u, int v)
{
tote++;
ee[tote].v = v;
ee[tote].next = pre[u];
pre[u] = tote;
}
void dfs1(int i = 1)
{
sz[i] = 1, son[i] = 0;
for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v != fa[i])
{
int v = ee[j].v;
fa[v] = i;
dep[v] = dep[i] + 1;
dfs1(v);
sz[i] += sz[v];
if(sz[v] > sz[son[i]]) son[i] = v;
}
}
void dfs2(int i = 1)
{
if(son[i])
{
top[son[i]] = top[i];
w[son[i]] = ++totw;
dfs2(son[i]);
}
for(int j = pre[i]; j; j = ee[j].next) if(ee[j].v != fa[i] && ee[j].v != son[i])
{
int v = ee[j].v;
w[v] = ++totw;
dfs2(top[v] = v);
}
}
int sum[MAXN << 2], cov[MAXN << 2];
void Build(int l = 1, int r = n, int rt = 1)
{
cov[rt] = 0;
if(l >= r)
{
sum[rt] = val[l];
return ;
}
int m = (l + r) >> 1;
Build(lson), Build(rson);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void Update(int L, int R, int add, int l = 1, int r = n, int rt = 1)
{
if(L <= l && r <= R)
{
cov[rt] += add;
sum[rt] += add;
return ;
}
if(cov[rt])
{
cov[rt << 1] += cov[rt], cov[rt << 1 | 1] += cov[rt];
sum[rt << 1] += cov[rt], sum[rt << 1 | 1] += cov[rt];
cov[rt] = 0;
}
int m = (l + r) >> 1;
if(L <= m) Update(L, R, add, lson);
if(R > m) Update(L, R, add, rson);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
int Query(int p, int l = 1, int r = n, int rt = 1)
{
if(l >= r) return sum[rt];
if(cov[rt])
{
cov[rt << 1] += cov[rt], cov[rt << 1 | 1] += cov[rt];
sum[rt << 1] += cov[rt], sum[rt << 1 | 1] += cov[rt];
cov[rt] = 0;
}
int m = (l + r) >> 1;
int ret = 0;
if(p <= m) ret += Query(p, lson);
if(p > m) ret += Query(p, rson);
return ret;
}
char op[4];
int main()
{
// freopen("A.in", "r", stdin);
int m, p;
while(RD(n))
{
RD(m), RD(p);
init();
for(int i = 1; i <= n; i++) RD(a[i]);
for(int i = 1; i <= m; i++)
{
int u, v;
RD(u), RD(v);
add_edge(u, v);
add_edge(v, u);
}
dfs1();
dfs2();
for(int i = 1; i <= n; i++) val[w[i]] = a[i];
// for(int i = 1; i <= n; i++) cout << i << ": " << w[i] << ' ' << son[i] << ' ' << top[i] << ' ' << fa[i] << endl;
Build();
while(p--)
{
scanf("%s", op);
if(op[0] == 'Q')
{
int x; RD(x);
printf("%d\n", Query(w[x]));
}
else
{
int c1, c2, k;
RD(c1), RD(c2), RD(k);
if(op[0] == 'D') k = -k;
while (top[c1] != top[c2])
{
if (dep[top[c1]] < dep[top[c2]]) swap(c1, c2);
Update(w[top[c1]], w[c1], k);
c1 = fa[top[c1]];
}
if(dep[c1] < dep[c2]) swap(c1, c2);
Update(w[c2], w[c1], k);
}
}
}
return 0;
}