题目大意
给你n个数,接下来给你m个数的关系,有q个操作,分别是删除关系和询问当前集合的最大值
这道题目和显然普通的并查集是无法解决的,我们采用离线操作
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
const int MAXN = 1e5 + 5;
struct Edge {
int l, r, op;
}quest[MAXN];
int num[MAXN], w[MAXN], f[MAXN];
map<pair<int, int>, int> mp;
vector<int> ans;
void init(int n) {
for (int i = 0; i <= n; ++i) {
f[i] = i;
num[i] = w[i];
}
}
int find_(int x) {
int tmp = f[x];
if (x != f[x]) {
f[x] = find_(f[x]);
num[x] = max(num[x], num[tmp]);
}
return f[x];
}
void Union(int x, int y) {
int fx = find_(x);
int fy = find_(y);
if (fx == fy) {
return;
}
if (num[fx] > num[fy] || (num[fx] == num[fy] && fx <= fy)) {
f[fy] = fx;
}
else {
f[fx] = fy;
}
}
int main()
{
int n;
int u, v, first = 1;
while (cin >> n) {
if (first) {
first = 0;
}
else {
cout << endl;
}
ans.clear();
mp.clear();
for (int i = 0; i < n; ++i) {
cin >> w[i];
}
init(n);
int m;
cin >> m;
for(int i = 0; i < m; ++i){
cin >> u >> v;
if (u > v) {
swap(u, v);
}
mp[make_pair(u, v)] = 1;
}
int q;
cin >> q;
char opt[10];
for (int i = 0; i < q; ++i) {
cin >> opt;
if (opt[0] == 'q') {
cin >> u;
quest[i].l = u;
quest[i].op = 0;
}
else {
cin >> u >> v;
if (u > v) {
swap(u, v);
}
quest[i].l = u;
quest[i].r = v;
quest[i].op = 1;
mp[make_pair(u, v)] = 0;
}
}
for (map<pair<int, int>, int>::iterator it = mp.begin(); it != mp.end(); ++it) {
if (it->second) {
pair<int, int> tmpPair = it->first;
Union(tmpPair.first, tmpPair.second);
}
}
for (int i = q - 1; i >= 0; --i) {
if (quest[i].op == 1) {
Union(quest[i].l, quest[i].r);
}
else {
int xx = find_(quest[i].l);
if (num[xx] <= w[quest[i].l])
ans.push_back(-1);
else
ans.push_back(xx);
}
}
int len = ans.size();
for (int i = len - 1; i >= 0; --i) {
cout << ans[i] << endl;
}
}
return 0;
}