poj1985 The k-th Largest Group
阿新 • • 發佈:2019-02-11
When there are three numbers 2 and 2 and 1, the 2nd largest number is 2 and the 3rd largest number is 1.
題解:平衡樹。用並查集合並,刪除兩個點,同時把兩個點相加放入平衡樹。
程式碼(splay):
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int num[1000000],g[1000000],size[1000000],cnt[1000000],lc[1000000],rc[1000000],fa[1000000],val[1000000],root,tot; void clear(){ root=tot=0; memset(size,0,sizeof(size)); memset(cnt,0,sizeof(cnt)); } void updata(int x){ if(x){ size[x]=cnt[x]+(lc[x]?size[lc[x]]:0)+(rc[x]?size[rc[x]]:0); } } void zig(int x){ int y,z; if(!fa[x])return; y=fa[x];z=fa[y]; if(z) if(lc[z]==y)lc[z]=x; else rc[z]=x; fa[x]=z;fa[y]=x;fa[rc[x]]=y;lc[y]=rc[x];rc[x]=y; updata(y);updata(x); } void zag(int x){ int y,z; if(!fa[x])return; y=fa[x];z=fa[y]; if(z) if(lc[z]==y)lc[z]=x; else rc[z]=x; fa[x]=z;fa[y]=x;fa[lc[x]]=y;rc[y]=lc[x];lc[x]=y; updata(y);updata(x); } void splay(int &root,int x){ int y,z; while(fa[x]){ y=fa[x];z=fa[y]; if(z){ if(lc[z]==y&&lc[y]==x)zig(y),zig(x); else if(lc[z]==y&&rc[y]==x)zag(x),zig(x); else if(rc[z]==y&&lc[y]==x)zig(x),zag(x); else zag(y),zag(x); } else if(lc[y]==x)zig(x); else zag(x); } root=x; } void sp(int x){ splay(root,x); } void insert(int &k,int key,int p){ if(!k){ size[k=++tot]=cnt[k]=1; lc[k]=rc[k]=0; val[k]=key; fa[k]=p; sp(k); return; } size[k]++; if(key==val[k]){ cnt[k]++; return; } if(key<val[k])insert(lc[k],key,k); else insert(rc[k],key,k); } void ins(int key){ if(!root){ size[root=++tot]=cnt[root]=1; lc[root]=rc[root]=0; val[root]=key;fa[root]=0; return; } insert(root,key,0); } int find(int k,int key){ while(k){ if(val[k]==key)break; k=key<val[k]?lc[k]:rc[k]; } if(k)sp(k); return k; } int fin(int key){ return find(root,key); } int getmin(int k){ return lc[k]?getmin(lc[k]):k; } int getmax(int k){ return rc[k]?getmax(rc[k]):k; } void del(int key){ int ls,rs,x,lson; x=fin(key);ls=lc[x];rs=rc[x]; if(!x)return; if(--cnt[x])return; if(!ls&&!rs){ clear(); return; } if(!ls)root=rs,fa[rs]=0; else if(!rs)root=ls,fa[ls]=0; else{ lson=getmax(ls); swap(lson,ls); fa[lson]=0;sp(ls); rc[ls]=rs;fa[rs]=ls;updata(ls); } } int findkth(int k){ int t; t=root; while(t){ if(size[lc[t]]<k&&k<=size[lc[t]]+cnt[t])break; if(k<=size[lc[t]])t=lc[t]; else k-=size[lc[t]]+cnt[t],t=rc[t]; } sp(t); return t; } int findd(int t){ if(t==g[t])return t; g[t]=findd(g[t]); return g[t]; } int main(){ int n,m,i,t1,t,k,x,y; scanf("%d%d",&n,&m); for(i=1;i<=n;i++)g[i]=i,num[i]=1; for(i=1;i<=n;i++)ins(1); for(i=1;i<=m;i++){ scanf("%d",&t1); if(t1==0){ scanf("%d%d",&t,&k); x=findd(t);y=findd(k); if(x!=y){ g[x]=y; del(num[x]);del(num[y]); num[y]+=num[x]; ins(num[y]); n--; } } else{ scanf("%d",&t); printf("%d\n",val[findkth(n-t+1)]); } } }