1 /**
2 problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966
3 裸板
4 **/
5 #include<stdio.h>
6 #include<stdlib.h>
7 #include<string.h>
8 #include<vector>
9 using namespace std;
10
11 const int MAXN = 500005;
12
13 template <typename T>
14 class SegmentTree {
15 private:
16 struct Node {
17 int left, right;
18 T sum, lazy;
19 } node[MAXN << 2];
20 T data[MAXN];
21 void pushUp(int root) {
22 node[root].sum = node[root << 1].sum + node[root << 1 | 1].sum;
23 }
24 void pushDown(int root) {
25 if(node[root].left == node[root].right) return;
26 int lson = root << 1;
27 int rson = root << 1 | 1;
28 node[lson].sum += node[root].lazy * (node[lson].right - node[lson].left + 1);
29 node[rson].sum += node[root].lazy * (node[rson].right - node[rson].left + 1);
30 node[lson].lazy += node[root].lazy;
31 node[rson].lazy += node[root].lazy;
32 node[root].lazy = 0;
33 }
34 public:
35 void build(int left, int right, int root = 1) {
36 node[root].left = left;
37 node[root].right = right;
38 node[root].lazy = 0;
39 if(left == right) {
40 node[root].sum = data[left];
41 } else {
42 int mid = (left + right) >> 1;
43 build(left, mid, root << 1);
44 build(mid + 1, right, root << 1 | 1);
45 pushUp(root);
46 }
47 }
48 void update(int left, int right, T value, int root = 1) {
49 int lson = root << 1;
50 int rson = root << 1 | 1;
51 node[root].sum += value * (right - left + 1);
52 if(node[root].left == left && node[root].right == right) {
53 node[root].lazy += value;
54 return ;
55 }
56 if(left >= node[rson].left) {
57 update(left, right, value, rson);
58 } else if(right <= node[lson].right) {
59 update(left, right, value, lson);
60 } else {
61 update(left, node[lson].right, value, lson);
62 update(node[rson].left, right, value, rson);
63 }
64 }
65 T query(int left, int right, int root = 1) {
66 int lson = root << 1;
67 int rson = root << 1 | 1;
68 if(node[root].lazy) pushDown(root);
69 if(node[root].left == left && node[root].right == right) {
70 return node[root].sum;
71 }
72 if(left >= node[rson].left) {
73 return query(left, right, rson);
74 } else if(right <= node[lson].right) {
75 return query(left, right, lson);
76 } else {
77 return query(left, node[lson].right, lson) + query(node[rson].left, right, rson);
78 }
79 }
80 void clear(int n, const vector<int> &d) {
81 for(int i = 1; i <= n; i ++) {
82 this->data[i] = d[i];
83 }
84 build(1, n);
85 }
86 };
87
88 template <typename T>
89 class TreeToLink {
90 private:
91 struct Point {
92 int size, son, depth, father, top, newId;
93 T data;
94 } point[MAXN];
95 struct Edge {
96 int to, next;
97 } edge[MAXN << 1];
98 int oldId[MAXN], first[MAXN], sign, sumOfPoint, cnt;
99 SegmentTree<T> st;
100 void dfs1(int u, int father = 0, int depth = 1) {
101 point[u].depth = depth;
102 point[u].father = father;
103 point[u].size = 1;
104 int maxson = -1;
105 for(int i = first[u]; i != -1; i = edge[i].next) {
106 int to = edge[i].to;
107 if(to == father) continue;
108 dfs1(to, u, depth + 1);
109 point[u].size += point[to].size;
110 if(point[to].size > maxson) {
111 point[u].son = to;
112 maxson = point[to].size;
113 }
114 }
115 }
116 void dfs2(int u, int top) {
117 point[u].newId = ++cnt;
118 oldId[cnt] = u;
119 point[u].top = top;
120 if(point[u].son == -1) {
121 return ;
122 }
123 dfs2(point[u].son, top);
124 for(int i = first[u]; i != -1; i = edge[i].next) {
125 int to = edge[i].to;
126 if(to == point[u].son || to == point[u].father) continue;
127 dfs2(to, to);
128 }
129 }
130 public:
131 void clear(int n) {
132 sumOfPoint = n;
133 sign = 0;
134 cnt = 0;
135 for(int i = 1; i <= n; i ++) {
136 first[i] = -1;
137 point[i].son = -1;
138 scanf("%d", &point[i].data);
139 }
140 }
141 void addEdgeOneWay(int u, int v) {
142 edge[sign].to = v;
143 edge[sign].next = first[u];
144 first[u] = sign ++;
145 }
146 void addEdgeTwoWay(int u, int v) {
147 addEdgeOneWay(u, v);
148 addEdgeOneWay(v, u);
149 }
150 void preWork(int x = 1) {
151 dfs1(x);
152 dfs2(x, x);
153 vector<int> data(sumOfPoint + 1);
154 for(int i = 1; i <= sumOfPoint; i ++) {
155 data[i] = point[oldId[i]].data;
156 }
157 st.clear(sumOfPoint, data);
158 }
159 void updatePath(int x, int y, T z){
160 while(point[x].top != point[y].top){
161 if(point[point[x].top].depth < point[point[y].top].depth)
162 swap(x, y);
163 st.update(point[point[x].top].newId, point[x].newId, z);
164 x = point[point[x].top].father;
165 }
166 if(point[x].depth > point[y].depth)
167 swap(x, y);
168 st.update(point[x].newId, point[y].newId, z);
169 }
170 T queryPath(int x, int y){
171 T ans = 0;
172 while(point[x].top != point[y].top){
173 if(point[point[x].top].depth < point[point[y].top].depth)
174 swap(x, y);
175 ans += st.query(point[point[x].top].newId, point[x].newId);
176 x = point[point[x].top].father;
177 }
178 if(point[x].depth > point[y].depth)
179 swap(x, y);
180 ans += st.query(point[x].newId, point[y].newId);
181 return ans;
182 }
183 void updateSon(int x, T z){
184 st.update(point[x].newId, point[x].newId + point[x].size - 1, z);
185 }
186 T querySon(int x){
187 return st.query(point[x].newId, point[x].newId + point[x].size - 1);
188 }
189 T queryPoint(int x) {
190 return queryPath(x, x);
191 }
192 void updatePoint(int x, T z) {
193 updatePath(x, x, z);
194 }
195 };
196
197 class Solution {
198 private:
199 int n, m, p;
200 TreeToLink<int> ttl;
201 public:
202 void solve() {
203 while(~scanf("%d%d%d", &n, &m, &p)){
204 ttl.clear(n);
205 for(int i = 0, a, b; i < m; i ++) {
206 scanf("%d%d", &a, &b);
207 ttl.addEdgeTwoWay(a, b);
208 }
209 ttl.preWork();
210 while(p --) {
211 char opt;
212 int a, b, c;
213 scanf(" %c%d", &opt, &a);
214 if(opt == 'I') {
215 scanf("%d%d", &b, &c);
216 ttl.updatePath(a, b, c);
217 } else if(opt == 'D') {
218 scanf("%d%d", &b, &c);
219 ttl.updatePath(a, b, -c);
220 } else if(opt == 'Q') {
221 printf("%d\n", ttl.queryPoint(a));
222 }
223 }
224 }
225 }
226 } DarkScoCu;
227
228 int main() {
229 DarkScoCu.solve();
230 return 0;
231 }