【BZOJ】【P2733】【HNOI2012】【永无乡】【题解】【启发式合并】

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2733

水启发式合并

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=5e5+10;
int n,m,q;
int getint(){
	int res=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
	return res;
}
int rnd(){
	static int KEY=12345678;
	return KEY+=KEY<<2|1;
}
struct node{
	int val,key,size,s;
	node *c[2];
    void rz(){  
        size=c[0]->size+s+c[1]->size;  
    }  
    void set(int _val=0,int _key=rnd(),int _size=1,int _s=1,node *C=NULL){  
        val=_val;key=_key;size=_size;s=_s;c[0]=c[1]=C;  
    }  
};
node pool[maxn];
node* newnode(){
	static int tot=0;
	if(tot<maxn)return &pool[tot++];
	return new node();
}
struct Treap{
	node *root,*Null;
	Treap(){
		Null=newnode();
		Null->set(0,INT_MAX,0,0,Null);
		root=Null;
	}	
   void rot(node *&t,bool d){  
        node *p=t->c[d];t->c[d]=p->c[!d];  
        p->c[!d]=t;t->rz();p->rz();t=p;  
    }  
    void _insert(node *&t,int x){  
        if(t==Null){t=newnode();t->set(x,rnd(),1,1,Null);return;}  
        if(t->val==x){t->size+=1;t->s+=1;return;}  
        _insert(t->c[x>t->val],x);  
        if(t->c[x>t->val]->key<t->key)rot(t,x>t->val);  
        else t->rz();  
    }  
	int _kth(node *t,int x){
        int r=t->c[0]->size;  
        if(t==Null)return 0;  
        else if(x<=r)return _kth(t->c[0],x);  
        else if(x>r+t->s)return _kth(t->c[1],x-r-t->s);  
        else return t->val;  
	}
	void insert(int x){_insert(root,x);}
	int kth(int x){return _kth(root,x);}
	int size(){return root->size;}
}T[maxn];
int fa[maxn];
int find(int x){
	if(fa[x]!=x)return fa[x]=find(fa[x]);return x;
}
void Union(int x,int y){
	int fax=find(x),fay=find(y);
	if(fax==fay)return;
	if(T[fax].size()<T[fay].size())swap(x,y),swap(fax,fay);
	fa[fay]=fax;
	for(int i=0;i<T[fay].size();i++){
		int val=T[fay].kth(i+1);
		T[fax].insert(val);
	}
}
pair<int,int> ps[maxn];
map<int,int>M;
int main(){
	n=getint();m=getint();
	for(int i=1;i<=n;i++){
		int x=getint();
		ps[i].first=x;ps[i].second=i;fa[i]=i;
	}sort(ps+1,ps+1+n);
	for(int i=1;i<=n;i++){
		T[ps[i].second].insert(i);
		M[i]=ps[i].second;
	}
	for(int i=1;i<=m;i++){
		int u=getint(),v=getint();
		Union(u,v);	
	}q=getint();
	while(q--){
		char o=getchar();
		while(o!='B'&&o!='Q')o=getchar();
		if(o=='B'){
			int u=getint(),v=getint();
			Union(u,v);
		}else{
			int u=find(getint()),k=getint();	
			if(k>T[u].size())puts("-1");		
			else printf("%d\n",M[T[u].kth(k)]);
		}
	}
	return 0;
}


你可能感兴趣的:(bzoj,省选)