hdu 1512
思路:用并查集即可,每次合并的时候将小的集合合并到大的集合上去。理论上的平均复杂度是n*lgn*lgn。
#include<map> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define Maxn 100010 #define LL long long #define Mod 1000000007 int sz[Maxn],fa[Maxn]; using namespace std; priority_queue<int> q[Maxn]; void init() { for(int i=0;i<Maxn;i++){ sz[i]=1; fa[i]=i; } } int find(int x) { if(x!=fa[x]) fa[x]=find(fa[x]); return fa[x]; } int merg(int a,int b) { int x=find(a); int y=find(b); if(x==y) return 0; int s1,s2; s1=q[x].top(); s2=q[y].top(); q[x].pop(); q[y].pop(); s1/=2; s2/=2; if(sz[x]>sz[y]){ q[x].push(s1); q[x].push(s2); while(!q[y].empty()){ q[x].push(q[y].top()); q[y].pop(); } printf("%d\n",q[x].top()); sz[x]+=sz[y]; fa[y]=x; }else{ q[y].push(s1); q[y].push(s2); while(!q[x].empty()){ q[y].push(q[x].top()); q[x].pop(); } printf("%d\n",q[y].top()); sz[y]+=sz[x]; fa[x]=y; } return 1; } int main() { int n,m,i,j; while(scanf("%d",&n)!=EOF){ init(); for(i=0;i<Maxn;i++){ while(!q[i].empty()) q[i].pop(); } int val; for(i=1;i<=n;i++){ scanf("%d",&val); q[i].push(val); } scanf("%d",&m); int a,b; for(i=1;i<=m;i++){ scanf("%d%d",&a,&b); if(!merg(a,b)) printf("-1\n"); } } return 0; }