您的位置:首页 > 其它

【pb_ds】【平衡树启发式合并】【并查集】bzoj2733 [HNOI2012]永无乡

2014-09-13 09:32 585 查看
用并查集维护联通性。对每个联通块维护一个平衡树。合并时启发式合并。比较懒,用了pb_ds。

#include<cstdio>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> T[100001];
tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>::iterator it;
int num[100001],val[100001],fa[100001],rank[100001];
int n,m,q,x,y,f1,f2;
char op[2];
int Res,Num;char C,CH[20];
inline int G()
{
Res=0;C='*';
while(C<'0'||C>'9')C=getchar();
while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
return Res;
}
inline void P(int x)
{
Num=0;while(x>0)CH[++Num]=x%10,x/=10;
while(Num)putchar(CH[Num--]+48);
putchar('\n');
}
void init()
{
for(int i=1;i<=n;i++)
fa[i]=i;
}
int findroot(int x)
{
if(fa[x]==x)
return x;
int rt=findroot(fa[x]);
fa[x]=rt;
return rt;
}
void Union(const int &u,const int &v)
{
if(rank[u]<rank[v])
{
fa[u]=v;
for(it=T[u].begin();it!=T[u].end();it++)
T[v].insert((*it));
T[u].clear();
}
else
{
fa[v]=u;
for(it=T[v].begin();it!=T[v].end();it++)
T[u].insert((*it));
T[v].clear();
if(rank[u]==rank[v]) rank[u]++;
}
}
int main()
{
n=G();m=G();
init();
for(int i=1;i<=n;i++)
{
val[i]=G();
T[i].insert(val[i]);
num[val[i]]=i;
}
for(int i=1;i<=m;i++)
{
x=G();y=G();
f1=findroot(x),f2=findroot(y);
if(f1!=f2) Union(f1,f2);
}
q=G();
for(int i=1;i<=q;i++)
{
scanf("%s",op);x=G();y=G();
if(op[0]=='Q')
{
f1=findroot(x);
if(T[f1].size()<y) puts("-1");
else P(num[*T[f1].find_by_order(y-1)]);
}
else
{
f1=findroot(x),f2=findroot(y);
if(f1!=f2) Union(f1,f2);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: