题目大意:
给你n个小根堆,每个堆初始有一个元素。有两个操作:
1. 把第x个数和第y个数所在的堆合并(如果第x个数或第y个数已经被删除or它们已经在同一个堆内则忽略)
2. 输出第x个数所在堆的堆顶元素,并将这个堆顶元素弹出堆(如果第x个数不存在则输出-1)
如果第$a_i$个数与第$a_j$个数相同,则比较i与j的大小。
解题思路:
可并堆嘛。话说随机化期望值还是蛮高的,于是随机堆+并查集水过。
嗯……平板电视大法也不错呀,不过空间占用貌似有点多啊(还好还好没超)。
随机堆:
C++ Code:
#include<bits/stdc++.h>
int n,m,fa[100005],vis[100005];
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
struct Heap{
Heap *ls,*rs;
int s,id;
Heap(int t=0,int num=0){
ls=rs=NULL;
s=t;
id=num;
}
inline bool operator<(const Heap& rhs)const{
if(s!=rhs.s)return s<rhs.s;
return id<rhs.id;
}
}*a[100005];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
Heap* merge(Heap*& a,Heap*& b){
if(a==NULL)return b;
if(b==NULL)return a;
if((*b)<(*a))std::swap(a,b);
if(rand()&1)a->rs=merge(a->rs,b);else
a->ls=merge(a->ls,b);
return a;
}
int Delete(Heap*& p){
int id=p->id;
p=merge(p->ls,p->rs);
return id;
}
int main(){
#ifdef LOCALJUDGE
freopen("testdata.in","r",stdin);
freopen("testdata.out","w",stdout);
#endif
srand(20170607);
memset(vis,0,sizeof vis);
n=readint(),m=readint();
for(int i=1;i<=n;++i)fa[i]=i,a[i]=new Heap(readint(),i);
while(m--){
int opt=readint();
if(opt==1){
int x=readint(),y=readint();
int a=find(x),b=find(y);
if(vis[y]||vis[x]||!a||!b)continue;
if(a!=b){
fa[b]=a;
::a[a]=merge(::a[a],::a[b]);
}
}else{
int x=readint();
int p=find(x);
if(!p||vis[x]||a[p]==NULL){
puts("-1");
continue;
}
printf("%d\n",a[p]->s);
int id=Delete(a[p]);
vis[id]=1;
}
}
return 0;
}
pbds:
C++ Code:
#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
__gnu_pbds::priority_queue<pair<int,int>,greater<pair<int,int> >,__gnu_pbds::thin_heap_tag>a[100005];
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0');
return d;
}
bool vis[100005];
int n=readint(),m=readint(),fa[100005];
inline int dad(int x){return x==fa[x]?x:fa[x]=dad(fa[x]);}
int main(){
memset(vis,0,sizeof vis);
for(int i=1;i<=n;++i)a[i].push(make_pair(readint(),i)),fa[i]=i;
while(m--){
int opt=readint();
if(opt==1){
int x=readint(),y=readint();
if(vis[x]||vis[y])continue;
x=dad(x),y=dad(y);
if(x!=y){
fa[y]=x;
a[x].join(a[y]);
}
}else{
int x=readint();
int f=dad(x);
if(vis[x]){
puts("-1");
continue;
}
pair<int,int>p=a[f].top();
a[f].pop();
printf("%d\n",p.first);
vis[p.second]=1;
}
}
return 0;
}