#include <stdio.h>
#include <string>
#include <iostream>
#define Maxn 300005
using namespace std;
int n, m, a[Maxn], root[Maxn], alt, cnt, fa[Maxn], tree[Maxn << 2], maxx, tag[Maxn << 2], L[Maxn], R[Maxn], tot;
int max(int a,int b) {
return a > b ? a : b;
}
int find(int x) {
return root[x] == x ? x : root[x] = find(root[x]);
}
void push_up(int x) {
tree[x] = max(tree[L[x]] + tag[L[x]] , tree[R[x]] + tag[R[x]]);
}
void merge(int x, int y) {
L[++ tot] = find(x), R[tot] = find(y);
root[tot] = fa[R[tot]] = fa[tot] = fa[L[tot]] = root[R[tot]] = root[L[tot]] = tot;
push_up(tot);
}
int query(int x) {
return fa[x] == x ? tag[x] : tag[x] + query(fa[x]);
}
void add(int x, int k) {
tag[find(x)] += k;
if(tree[find(maxx)] + tag[find(maxx)] < tree[find(x)] + tag[find(x)] ) maxx = find(x);
}
void upd(int x) {
if(root[x] == x){
if(tree[x] + tag[x] > tree[find(maxx)] + tag[find(maxx)]) maxx = x;
else return;
}
else if(tree[x] + tag[x] > tree[fa[x]]) {
push_up(fa[x]), upd(fa[x]);
}
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) {
scanf("%d", &a[i]);
tree[i] = a[i];
root[i] = fa[i] = i;
if(a[i] > a[maxx]) maxx = i;
}
tot = n;
scanf("%d", &m);
string s;
int x, y, i;
for(i = 1; i <= m; ++ i) {
cin >> s;
if(s[0] == 'U') {
scanf("%d%d", &x, &y);
if(find(x) != find(y)) merge(x, y);
} else if (s[0] == 'A') {
if(s[1] == '1') {
scanf("%d%d", &x, &y);
a[x] += y;
tree[x] += y;
upd(x);
} else if(s[1] == '2') {
scanf("%d%d", &x, &y);
add(x, y);
} else if(s[1] == '3') {
scanf("%d", &x);
alt += x;
}
} else {
if(s[1] == '1') {
scanf("%d", &x);
printf("%d\n", tree[x] + alt + query(x));
} else if(s[1] == '2') {
scanf("%d", &x);
printf("%d\n", tree[find(x)] + alt + tag[find(x)]);
} else {
printf("%d\n", tree[find(maxx)] + tag[find(maxx)] + alt);
}
}
}
}
思路大概就是 合并联通块时把两个联通块的 root 合并到一个新的节点 作为 root。 每次联通块加都在 root 打上 tag,算单点的时候统计下 到 root 路径上的 tag 和 ai 加起来即可,不知道为什么 WA 了 9个点