#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
#define pb push_back
int mod = 998244353;
ll INF = (ll)1e18;
template<typename T>
T chmax(T a, T b) {
return a > b ? a : b;
}
template<typename T>
T chmin(T a, T b) {
return a > b ? b : a;
}
const int N = (int)1e6 + 1;
struct DSU{
vector<int> node, size;
DSU(){}
DSU(int n){
init(n);
}
void init(int n){
node.resize(n);
size.resize(n);
for(int i = 0; i < n; i++){
node[i] = i;
size[i] = 1;
}
}
int find(int x){
return x == node[x] ? x : node[x] = find(node[x]);
}
void erase(int x){
size[find(x)] -= 1;
node[x] = x;
}
void relocate(int x, int y){ //can't be root
int dx = find(x), dy = find(y);
if(dx == dy){
return;
}
node[x] = dy;
size[dx] -= 1;
size[dy] += 1;
}
int set(int x, int y){
return find(x) == find(y);
}
int merge(int x, int y){
x = find(x);
y = find(y);
if(x == y){
return 0;
}
size[x] += size[y];
node[y] = x;
return 1;
}
int heuristic_merge(int x, int y){
x = find(x);
y = find(y);
if(size[x] < size[y]){
swap(x, y);
}
return merge(x, y);
}
int get(int x){
return size[find(x)];
}
};
template<class Operation>
struct SegTree{
const ll n, len;
ll pos, root;
struct Node {
ll l, r;
Operation op;
};
vector<Node> f;
SegTree(ll n, ll len) : n(n), len(len), f(4 << __lg(n)), pos(0), root(0){}
void pushup(ll u) {
f[u].op = f[f[u].l].op + f[f[u].r].op;
}
void update(ll &u, ll l, ll r, ll x, const Operation &v){
if(!u){
u = ++pos;
f[u].op = {};
f[u].l = f[u].r = 0;
}
if(l == r){
f[u].op = v; //也许会变
return;
}
ll m = (l + r) >> 1;
if(x <= m) {
update(f[u].l, l, m, x, v);
}
else{
update(f[u].r, m + 1, r, x, v);
}
pushup(u);
}
void update(ll &root, ll u, const Operation &v){
update(root, 1, len, u, v);
}
void modify(ll u, ll v){
f[u].op.sum = f[v].op.sum;
f[u].op.cnt = f[v].op.cnt;
}
ll merge(ll u, ll v, ll l, ll r){
if(!u){
return v;
}
if(!v){
return u;
}
if(l == r){
modify(u, v);
return u;
}
ll m = (l + r) >> 1;
f[u].l = merge(f[u].l, f[v].l, l, m);
f[u].r = merge(f[u].r, f[v].r, m + 1, r);
pushup(u);
return u;
}
Operation query(ll u, ll l, ll r, ll x, ll y){
if(!u){
return {};
}
if(x <= l && r <= y) {
return f[u].op;
}
ll m = (l + r) >> 1;
Operation cur;
if(x <= m) {
cur = query(f[u].l, l, m, x, y);
}
if(y > m) {
cur = cur + query(f[u].r, m + 1, r, x, y);
}
return cur;
}
Operation query(ll &root, ll l, ll r){
return query(root, 1, len, l, r);
}
};
//预处理根
struct Operation{
ll sum, cnt;
Operation(ll p = 0){
if(p){
sum = p;
cnt = 1;
}
else{
sum = 0;
cnt = 0;
}
}
};
Operation operator+(Operation a, Operation b){
Operation c;
if(!a.cnt) return b;
c.sum = a.sum + b.sum;
c.cnt = a.cnt + b.cnt;
return c;
}
void solve(){
int n, m;
cin >> n >> m;
ll a[n + 1], root[n + 1];
for(int i = 1; i <= n; i++){
cin >> a[i];
root[i] = i;
}
SegTree<Operation> tr(N, n);
DSU dsu(N);
tr.pos = n;
for(int i = 1; i <= n; i++){
tr.update(root[i], a[i], {i});
}
for(int i = 1; i <= m; i++){
int u, v;
cin >> u >> v;
if(dsu.set(u, v)) continue;
u = dsu.find(u), v = dsu.find(v);
if(dsu.get(u) >= dsu.get(v)){
tr.merge(u, v, 1, n);
}
else{
tr.merge(v, u, 1, n);
}
dsu.heuristic_merge(u, v);
}
int q;
cin >> q;
for(int i = 1; i <= q; i++){
char op;
cin >> op;
int x, k;
cin >> x >> k;
if(op == 'Q'){
int l = 1, r = n + 1;
x = dsu.find(x);
while(l < r){
int m = l + r >> 1;
if(tr.query(root[x], 1, m).cnt >= k) r = m;
else l = m + 1;
}
auto qwq = tr.query(root[x], 1, l);
if(qwq.cnt < k || qwq.cnt > k){
cout << -1 << endl;
}
else{
cout << tr.query(root[x], l, l).sum << endl;
}
}
else{
if(dsu.set(x, k)) continue;
x = dsu.find(x), k = dsu.find(k);
if(dsu.get(x) >= dsu.get(k)){
tr.merge(root[x], root[k], 1, n);
}
else{
tr.merge(root[k], root[x], 1, n);
}
dsu.heuristic_merge(x, k);
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}
```[]()```cpp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
#define pb push_back
int mod = 998244353;
ll INF = (ll)1e18;
template<typename T>
T chmax(T a, T b) {
return a > b ? a : b;
}
template<typename T>
T chmin(T a, T b) {
return a > b ? b : a;
}
const int N = (int)1e6 + 1;
struct DSU{
vector<int> node, size;
DSU(){}
DSU(int n){
init(n);
}
void init(int n){
node.resize(n);
size.resize(n);
for(int i = 0; i < n; i++){
node[i] = i;
size[i] = 1;
}
}
int find(int x){
return x == node[x] ? x : node[x] = find(node[x]);
}
void erase(int x){
size[find(x)] -= 1;
node[x] = x;
}
void relocate(int x, int y){ //can't be root
int dx = find(x), dy = find(y);
if(dx == dy){
return;
}
node[x] = dy;
size[dx] -= 1;
size[dy] += 1;
}
int set(int x, int y){
return find(x) == find(y);
}
int merge(int x, int y){
x = find(x);
y = find(y);
if(x == y){
return 0;
}
size[x] += size[y];
node[y] = x;
return 1;
}
int heuristic_merge(int x, int y){
x = find(x);
y = find(y);
if(size[x] < size[y]){
swap(x, y);
}
return merge(x, y);
}
int get(int x){
return size[find(x)];
}
};
template<class Operation>
struct SegTree{
const ll n, len;
ll pos, root;
struct Node {
ll l, r;
Operation op;
};
vector<Node> f;
SegTree(ll n, ll len) : n(n), len(len), f(4 << __lg(n)), pos(0), root(0){}
void pushup(ll u) {
f[u].op = f[f[u].l].op + f[f[u].r].op;
}
void update(ll &u, ll l, ll r, ll x, const Operation &v){
if(!u){
u = ++pos;
f[u].op = {};
f[u].l = f[u].r = 0;
}
if(l == r){
f[u].op = v; //也许会变
return;
}
ll m = (l + r) >> 1;
if(x <= m) {
update(f[u].l, l, m, x, v);
}
else{
update(f[u].r, m + 1, r, x, v);
}
pushup(u);
}
void update(ll &root, ll u, const Operation &v){
update(root, 1, len, u, v);
}
void modify(ll u, ll v){
f[u].op.sum = f[v].op.sum;
f[u].op.cnt = f[v].op.cnt;
}
ll merge(ll u, ll v, ll l, ll r){
if(!u){
return v;
}
if(!v){
return u;
}
if(l == r){
modify(u, v);
return u;
}
ll m = (l + r) >> 1;
f[u].l = merge(f[u].l, f[v].l, l, m);
f[u].r = merge(f[u].r, f[v].r, m + 1, r);
pushup(u);
return u;
}
Operation query(ll u, ll l, ll r, ll x, ll y){
if(!u){
return {};
}
if(x <= l && r <= y) {
return f[u].op;
}
ll m = (l + r) >> 1;
Operation cur;
if(x <= m) {
cur = query(f[u].l, l, m, x, y);
}
if(y > m) {
cur = cur + query(f[u].r, m + 1, r, x, y);
}
return cur;
}
Operation query(ll &root, ll l, ll r){
return query(root, 1, len, l, r);
}
};
//预处理根
struct Operation{
ll sum, cnt;
Operation(ll p = 0){
if(p){
sum = p;
cnt = 1;
}
else{
sum = 0;
cnt = 0;
}
}
};
Operation operator+(Operation a, Operation b){
Operation c;
if(!a.cnt) return b;
c.sum = a.sum + b.sum;
c.cnt = a.cnt + b.cnt;
return c;
}
void solve(){
int n, m;
cin >> n >> m;
ll a[n + 1], root[n + 1];
for(int i = 1; i <= n; i++){
cin >> a[i];
root[i] = i;
}
SegTree<Operation> tr(N, n);
DSU dsu(N);
tr.pos = n;
for(int i = 1; i <= n; i++){
tr.update(root[i], a[i], {i});
}
for(int i = 1; i <= m; i++){
int u, v;
cin >> u >> v;
if(dsu.set(u, v)) continue;
u = dsu.find(u), v = dsu.find(v);
if(dsu.get(u) >= dsu.get(v)){
tr.merge(u, v, 1, n);
}
else{
tr.merge(v, u, 1, n);
}
dsu.heuristic_merge(u, v);
}
int q;
cin >> q;
for(int i = 1; i <= q; i++){
char op;
cin >> op;
int x, k;
cin >> x >> k;
if(op == 'Q'){
int l = 1, r = n + 1;
x = dsu.find(x);
while(l < r){
int m = l + r >> 1;
if(tr.query(root[x], 1, m).cnt >= k) r = m;
else l = m + 1;
}
auto qwq = tr.query(root[x], 1, l);
if(qwq.cnt < k || qwq.cnt > k){
cout << -1 << endl;
}
else{
cout << tr.query(root[x], l, l).sum << endl;
}
}
else{
if(dsu.set(x, k)) continue;
x = dsu.find(x), k = dsu.find(k);
if(dsu.get(x) >= dsu.get(k)){
tr.merge(root[x], root[k], 1, n);
}
else{
tr.merge(root[k], root[x], 1, n);
}
dsu.heuristic_merge(x, k);
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}