P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并
Posted 昵称很长很长真是太好了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并相关的知识,希望对你有一定的参考价值。
题意:
B
x
y
B\\ x\\ y
B x y 表示在岛
x
x
x 与岛
y
y
y 之间修建一座新桥。
Q x k Q\\ x\\ k Q x k 表示询问当前与岛 x x x 连通的所有岛中第 k k k 重要的是哪座岛,即所有与岛 x x x 连通的岛中重要度排名第 k k k 小的岛是哪座,请你输出那个岛的编号。
题解:
一眼题,用并查集维护一下连通块,平衡树合并时用启发式合并,合并最多也就
n
l
o
g
n
nlogn
nlogn次,总时间复杂度位
O
(
n
l
o
g
n
2
)
O(nlogn^2)
O(nlogn2)
就是写代码的时候跟失了智一样,忘加一句话多调试了三小时,愚不可及
代码:
#include<bits/stdc++.h>
#define endl '\\n'
using namespace std;
const int maxn=5e5+10;
int a[maxn];
int f[maxn];
int ifind(int x)
if(x==f[x]) return x;
return f[x]=ifind(f[x]);
mt19937 rnd(233);
struct FHQ
int root[maxn],cnt;
int ls[maxn],rs[maxn],val[maxn],key[maxn],siz[maxn];
int newnode(int vals)
val[++cnt]=vals;
key[cnt]=rnd();
siz[cnt]=1;
return cnt;
void updata(int node)
siz[node]=siz[ls[node]]+siz[rs[node]]+1;
void spilt_val(int node,int vals,int &x,int &y)
if(!node)
x=y=0;
return;
if(val[node]<=vals)
x=node;
spilt_val(rs[node],vals,rs[node],y);
else
y=node;
spilt_val(ls[node],vals,x,ls[node]);
updata(node);
int mer(int x,int y)
if(!x||!y) return x+y;
if(key[x]>key[y])
rs[x]=mer(rs[x],y);
updata(x);
return x;
else
ls[y]=mer(x,ls[y]);
updata(y);
return y;
void mer_node(int tree,int nd)
int x,y;
spilt_val(root[tree],val[nd],x,y);
root[tree]=mer(mer(x,nd),y);
int x;
void dfs(int node)
if(!node) return ;
dfs(ls[node]);
dfs(rs[node]);
ls[node]=rs[node]=0; //!!摘掉以后记得清空
siz[node]=1;
mer_node(x,node);
// void lrd(int node)
// if(!node) return;
// //cout<<"dfs "<<node<<endl;
// lrd(ls[node]);
// lrd(rs[node]);
//
int merge_tree(int a,int b)
if(siz[root[a]]<siz[root[b]]) swap(a,b); //启发式,把b合并到a上
x=a;
dfs(root[b]);
return x;
int get_num(int tree,int rk)
int node=root[tree];
if(siz[node]<rk) return -1;
while(node)
if(siz[ls[node]]+1==rk) break;
else if(siz[ls[node]]>=rk) node=ls[node];
else
rk-=siz[ls[node]]+1;
node=rs[node];
return node;
fhq;
signed main()
ios::sync_with_stdio(false);
cin.tie(0);
for(int i=1;i<=100000;i++)
f[i]=i;
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
fhq.root[i]=fhq.newnode(a[i]);
for(int i=1;i<=m;i++)
int x,y;
cin>>x>>y;
int dx=ifind(x);
int dy=ifind(y);
if(dx!=dy)
int now=fhq.merge_tree(dx,dy);
f[dx]=now;
f[dy]=now;
int q;
cin>>q;
while(q--)
char opt;
cin>>opt;
if(opt=='Q')
int x,k;
cin>>x>>k;
x=ifind(x);
cout<<fhq.get_num(x,k)<<endl;
else
int x,y;
cin>>x>>y;
int dx=ifind(x);
int dy=ifind(y);
if(dx!=dy)
int now=fhq.merge_tree(dx,dy);
f[dx]=now;
f[dy]=now;
以上是关于P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ2733][P3224][HNOI2012]永无乡[平衡树+启发式合并+并查集]
P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并
P3224 [HNOI2012]永无乡 FHQ-Treap 启发式合并