樹鏈剖分模板
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <string.h>
#include <iostream>
#include <algorithm>
#define pi 3.14159265358979
#define mid (left+right)/2
#define ls (2*rt)
#define rs ((2*rt)+1)
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int N = 5e4+5;
const int inf = 0x7FFFFFFF;
const int mod = 998244353;
int read(){
char ch=getchar();int x=0,f=1;
while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
vector<int>G[N];
int w[N],step[N],fa[N],size[N],son[N];
int id[N],wt[N],top[N];
int tree[N<<2];
void dfs1(int u,int f,int deep){
step[u] = deep;//紀錄位於哪一層
fa[u] = f;//記錄父親結點
size[u] = 1;//記錄非葉子結點的子樹大小
int maxson = -1;//記錄重兒子的兒子數
int n = G[u].size();
for(int i = 0;i < n;i++){
int v = G[u][i];
if(v == f) continue;
dfs1(v,u,deep+1);
size[u] += size[v];//加上它兒子的個數
if(size[v] > maxson){
maxson = size[v];
son[u] = v;//記錄非葉子節點重兒子的編號
}
}
}
int cnt = 0;
void dfs2(int u,int topf){//u是當前結點,topf是當前鏈的最頂端的節點
id[u] = ++cnt;//標記每個點的新編號
wt[cnt] = w[u];
top[u] = topf;//這個點所在鏈的頂端
if(!son[u]) return;//如果沒有兒子返回
dfs2(son[u],topf);//對於非葉子節點,優先處理重兒子,再處理輕兒子
int n = G[u].size();
for(int i = 0;i < n;i++){
int v = G[u][i];
if(v == fa[u] || v == son[u]) continue;
dfs2(v,v);//對於每一個輕兒子都有一條從它自己開始的鏈
}
}
void build(int rt,int left,int right){
if(left == right){
tree[rt] = wt[left];
return;
}
build(ls,left,mid);
build(rs,mid+1,right);
}
void pushdown(int rt){
tree[ls] += tree[rt];
tree[rs] += tree[rt];
tree[rt] = 0;
}
void update(int rt,int left,int right,int l,int r,int k){
if(left >= l && right <= r){
tree[rt] += k;
return;
}
if(tree[rt]) pushdown(rt);
if(l <= mid) update(ls,left,mid,l,r,k);
if(r > mid) update(rs,mid+1,right,l,r,k);
}
void updrange(int x,int y,int k,int n){
while(top[x] != top[y]){
if(step[top[x]] < step[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],k);
x = fa[top[x]];
}
if(step[x] > step[y]) swap(x,y);
update(1,1,n,id[x],id[y],k);
}
int query(int rt,int left,int right,int k){
if(left == right){
return tree[rt];
}
if(tree[rt]) pushdown(rt);
if(k <= mid) return query(ls,left,mid,k);
else return query(rs,mid+1,right,k);
}
void solve(int n,int m,int q){
for(int i = 1;i <= n;i++){
w[i] = read();
}
for(int i = 1;i <= m;i++){
int u = read();
int v = read();
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
/*
for(int i = 1;i <= n;i++){
printf("%3d",w[i]);
}
cout<<endl;
for(int i = 1;i <= n;i++){
printf("%3d",id[i]);
}
cout<<endl;
for(int i = 1;i <= n;i++){
printf("%3d",wt[i]);
}
cout<<endl;
*/
while(q--){
char op;
cin >> op;
if(op == 'I'){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
updrange(l,r,k,n);
}else if(op == 'D'){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
updrange(l,r,-1*k,n);
}else if(op == 'Q'){
int u;
scanf("%d",&u);
cout<<query(1,1,n,id[u])<<endl;
}
}
}
void init(){
cnt = 0;
for(int i = 0;i < N;i++) G[i].clear();
memset(tree,0,sizeof tree);
memset(top,0,sizeof top);
memset(wt,0,sizeof wt);
memset(id,0,sizeof id);
memset(son,0,sizeof son);
memset(size,0,sizeof size);
memset(fa,0,sizeof fa);
memset(step,0,sizeof step);
}
int main(){
int n,m,q;
while(~scanf("%d%d%d",&n,&m,&q)){
init();
solve(n,m,q);
}
return 0;
}
/*
8 7
5 10 7 15 8 20 11 9
1 2
1 4
2 3
2 6
4 5
4 8
5 7
3 2 5
1 2 3
2 1
2 3
1 1 3 5
3 2
2 1 2 2
3 1
3 3
*/