题目大意:
给你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 ",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 ",p.first); vis[p.second]=1; } } return 0; }