可并堆模板题
SOL
直接用可并堆做。
2个操作
- 合并2个集合
- 查询1个点所在集合的最小值,并删除该点,如果这个点已经被
删除则输出0
集合合并用并查集实现就好了,至于最小值——堆来维护,手写堆。
裸的左偏树,然而不会……
#include<bits/stdc++.h>
using namespace std;
#define N 1000200
inline int rd(){
int data=0,w=1;static char ch=0;
ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
int n,m,rt[N],vis[N];
char ch[10];
int f[N];
int find(int x){return f[x]==x? x:f[x]=find(f[x]);}
struct tree{int l,r,d,w;}t[N];
int merge(int k1,int k2){
if(!k1||!k2)return k1+k2;
if(t[k1].w>t[k2].w)swap(k1,k2);
t[k1].r=merge(t[k1].r,k2);
if(t[t[k1].l].d<t[t[k1].r].d)swap(t[k1].l,t[k1].r);
t[k1].d=t[k1].r+1;
return k1;
}
void del (int &x){x=merge(t[x].l,t[x].r);}
int main(){
// freopen("play.in","r",stdin);
// freopen("play.out","w",stdout);
n=rd();
for(int register i=1;i<=n;i++){
f[i]=i;
rt[i]=i;
t[i].w=rd();
}
m=rd();
while(m--){
scanf("%s",ch);
if(ch[0]=='M'){
int x=rd(),y=rd();
if(vis[x]||vis[y])continue;
x=find(x),y=find(y);
if(x==y)continue;
f[x]=y;
rt[y]=merge(rt[x],rt[y]);
}
else{
int x=rd();
if(vis[x])printf("0\n");
else{
x=find(x);
printf("%d\n",t[rt[x]].w);
vis[rt[x]]=1;
del(rt[x]);
}
}
}
return 0;
}