思路:
删边可以倒着来看就变成加边,维护一个可撤销并查集的同时对每个点维护一个set来储存p值,那么询问就是询问一个联通块中最大的p,我们在合并的时候用启发式合并的思想对两个set进行合并即可。
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
int n,m,q,a[N];
vector<int>v[N];
struct uzi{
int x,y;
bool operator <(const uzi & t)const{
return y>t.y;
}
}p[N];
int op[N],po[N],del[N],f[N],sz[N];
int find(int x){
while(x!=f[x]){
x=f[x];
}
return x;
}
int st[N],tot;
set<uzi>G[N];
void merge(int x,int y){
int dx=find(x),dy=find(y);
if(dx==dy)
return;
if(sz[dx]>sz[dy])swap(dx,dy);
sz[dy]+=sz[dx];
f[dx]=dy;
st[++tot]=dx;
for(auto k:G[dx]){
G[dy].insert(k);
}
}
int nxt[N];
void er(int y){
while(tot>y){
int now=st[tot--];
sz[f[now]]-=sz[now];
for(auto k:G[now])if(G[f[now]].find(k)!=G[f[now]].end())G[f[now]].erase(k);
f[now]=now;
}
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>m>>q;
for(int i=1;i<=n;i++)cin>>a[i],f[i]=i,sz[i]=1,G[i].insert({i,a[i]});
for(int i=1;i<=m;i++){
int s,t;
cin>>s>>t;
p[i]={s,t};
}
for(int i=1;i<=q;i++){
cin>>op[i]>>po[i];
if(op[i]==2)del[po[i]]=1;
}
for(int i=1;i<=m;i++){
if(!del[i])merge(p[i].x,p[i].y);
}
nxt[q+1]=tot;
for(int i=q;i>=1;i--){
nxt[i]=nxt[i+1];
if(op[i]==2)merge(p[po[i]].x,p[po[i]].y),nxt[i]=tot;
}
for(int i=1;i<=q;i++){
if(op[i]==2)er(nxt[i+1]);
else{
int now=po[i];
int x=find(now);
//cout<<i<<' '<<now<<' '<<x<<' '<<sz[x]<<endl;
while(!G[x].empty()&&!a[(*G[x].begin()).x])G[x].erase(G[x].begin());
if(G[x].empty())cout<<0<<'\n';
else{
cout<<a[(*G[x].begin()).x]<<'\n';
a[(*G[x].begin()).x]=0;
}
}
}
return 0;
}