题意:
现在有一张图,每次有两种询问:
1 x 表示在x所在的连通块中,找到值最大的数输出,并且将那个值变成0
2 i 表示将第i条边删掉
题解:
将值变成0这个操作限制了我们一定要从前往后做。
但是我偏不,因为从前往后很难找到当前的连通块是什么,但是我们可以从后往前,对于当前如果是2操作,并且如果x和y不在一个集合内,就将其连起来。注意因为我们之后是要从前往后做的,所以不能路径压缩,需要使用启发式合并,将两个集合的数合并在一起。然后从前往后做的时候,再将大集合中删掉小集合的数。
大致思路就是这样,代码不是我敲的所以…就不解释了
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define pb push_back
#define eb emplace_back
#define mst(a,b) memset(a,b,sizeof(a))
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
#pragma GCC optimize(2)
#define ri register int
#define iv inline void
using namespace std;
const int N=3e5+5;
int f[N],ch[N][2],rev[N],siz[N];
const int SZ=1<<19;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
G;while(*ip<'-')G;
ri x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=998244353;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}
int n,m,q;
int orid[1000050];
int v[1000050];
set<int> st[1000050];
vector<int> vec[1000050];
vector<int> mainvec[1000050];
int a[1000050],b[1000050];
int opr[1000050],opid[1000050];
bool vis[1000050];
int gp[1000050];
/*int fnd(int p)
{
return p==gp[p]?p:(gp[p]=fnd(gp[p]));
}*/
void mergeTo(vector<int> &v,int a,int b)
{
a=gp[a];
b=gp[b];
if(a^b)
{
if(vec[a].size()>vec[b].size())
swap(a,b);
v=vec[a];
for(int &it:vec[a])
{
gp[it]=b;
vec[b].pb(it);
}
vec[a].clear();
}
}
void solve()
{
scanf("%d%d%d",&n,&m,&q);
rep(i,1,n)
{
scanf("%d",&v[i]);
orid[v[i]]=i;
gp[i]=i;
vec[i].pb(i);
}
rep(i,1,m)
scanf("%d%d",&a[i],&b[i]);
rep(i,1,q)
{
scanf("%d%d",&opr[i],&opid[i]);
if(opr[i]==2)
vis[opid[i]]=true;
}
rep(i,1,m)
{
if(!vis[i])
mergeTo(mainvec[0],a[i],b[i]);
}
per(i,q,1)
{
if(opr[i]==2)
mergeTo(mainvec[i],a[opid[i]],b[opid[i]]);
}
rep(i,1,n)
{
if(gp[i]==i)
{
for(int &it:vec[i])
st[i].insert(v[it]);
}
}
int gpid=n;
rep(i,1,q)
{
if(opr[i]==1)
{
bool flag=false;
int fa=gp[opid[i]];
//cerr<<"? "<<i<<' '<<fa<<' '<<st[fa].size()<<'\n';
while(!st[fa].empty())
{
auto it=st[fa].rbegin();
//cerr<<"! "<<fa<<' '<<st[fa].size()<<' '<<(*it)<<'\n';
if(gp[orid[*it]]==fa)
{
v[orid[*it]]=0;
flag=true;
cout<<(*it)<<'\n';
st[fa].erase(*it);
break;
}
st[fa].erase(*it);
}
if(!flag)
cout<<"0\n";
}
else
{
++gpid;
for(int &it:mainvec[i])
{
gp[it]=gpid;
if(v[it])
st[gpid].insert(v[it]);
}
}
}
}
int main()
{
closeSync;
//multiCase
{
solve();
}
return 0;
}