带删除维护最大值显然不好做,所以考虑先把最后的图建出来,再从后往前加边。
但是询问中还带修改(让 p u = 0 p_u=0 pu=0),这样会影响后面的询问,所以也不能加边时就得到答案。
这里给出一种简单易懂的做法:
在从后往前枚举操作的时候:
-
如果是加边 ( u , v ) (u,v) (u,v) 且 u u u 和 v v v 不连通(设它们所在连通块的根分别为 a a a、 b b b),我们就新建一个虚点连向 a a a、 b b b,并且把这个虚点作为 a a a、 b b b 的父亲。
-
如果是询问 x x x,也就是询问当前 x x x 所在连通块内的最大值,我们就记录一下当前 x x x 所在连通块的根。
建好新图后,我们再从前往后扫每一个询问。对于一个询问,我们直接查询我们对这个询问记录的根的子树内的最大值,然后把它置零。这些操作具体可以用 dfn 序线段树维护。
其实这个做法的巧妙之处就在于设置了一个虚点,这个虚点起到了一个类似可持久化记录和区分版本的作用。
代码如下:
#include<bits/stdc++.h>
#include<iostream>
#define N 200010
#define M 300010
#define K 500010
using namespace std;
struct Edge
{
int u,v;
}e[M];
struct Query
{
int opt,x;
}q[K];
struct data
{
int v,id;
data(){v=-1*1*1*1;}
data(int a,int b){v=a,id=b;}
}maxn[(N+K)<<2];
bool operator < (data a,data b)
{
return a.v<b.v;
}
int n,m,Q,v[N+K],fa[N+K];
int cnt,head[N+K],to[N+K],nxt[N+K];
int node,idx,dfn[N+K],rk[N+K],size[N+K];
bool del[M],vis[N+K];
int find(int x)
{
return x==fa[x]?x:(fa[x]=find(fa[x]));
}
void adde(int u,int v)
{
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int u)
{
dfn[u]=++idx;
rk[idx]=u;
size[u]=1;
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
dfs(v);
size[u]+=size[v];
}
}
void up(int k)
{
maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
}
void build(int k,int l,int r)
{
if(l==r)
{
maxn[k]=data(v[rk[l]],l);
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
up(k);
}
data query(int k,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr) return maxn[k];
int mid=(l+r)>>1;
data ans;
if(ql<=mid) ans=max(ans,query(k<<1,l,mid,ql,qr));
if(qr>mid) ans=max(ans,query(k<<1|1,mid+1,r,ql,qr));
return ans;
}
void update(int k,int l,int r,int x)
{
if(l==r)
{
maxn[k].v=0;
return;
}
int mid=(l+r)>>1;
if(x<=mid) update(k<<1,l,mid,x);
else update(k<<1|1,mid+1,r,x);
up(k);
}
int main()
{
scanf("%d%d%d",&n,&m,&Q);
node=n;
for(int i=1;i<=n;i++)
scanf("%d",&v[i]);
for(int i=1;i<=m;i++)
scanf("%d%d",&e[i].u,&e[i].v);
for(int i=1;i<=Q;i++)
{
scanf("%d%d",&q[i].opt,&q[i].x);
if(q[i].opt==2) del[q[i].x]=1;
}
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
if(!del[i])
{
int a=find(e[i].u),b=find(e[i].v);
if(a!=b)
{
fa[b]=a;
adde(a,b);
}
}
}
for(int i=Q;i>=1;i--)
{
if(q[i].opt==1) q[i].x=find(q[i].x);
else
{
int a=find(e[q[i].x].u),b=find(e[q[i].x].v);
if(a!=b)
{
++node;//新建虚点
fa[a]=fa[b]=fa[node]=node;
adde(node,a),adde(node,b);
}
}
}
for(int i=1;i<=node;i++)
{
int a=find(i);
if(!vis[a])
{
vis[a]=true;
dfs(a);
}
}
build(1,1,node);
for(int i=1;i<=Q;i++)
{
if(q[i].opt==1)
{
data ans=query(1,1,node,dfn[q[i].x],dfn[q[i].x]+size[q[i].x]-1);
printf("%d
",ans.v);
update(1,1,node,ans.id);
}
}
return 0;
}