题意:初始化状态为N个含单一元素的集合,动态合并任意两个集合,查询第ith大的集合的大小
分析:以虚二叉树做辅助结构找出第ith大的集合的大小
#include
<
iostream
>
#include
<
algorithm
>
using
namespace
std;
#define
MAXN 200001
int
v[MAXN],N,M,pnt[MAXN],son[
3
*
MAXN];
//
v[i]第i只猫所在组的猫的数量,范围在1~N之间;son[u]表示以结点u为根的子树的结点数
void
insert(
int
num,
int
k){
int
l
=
1
,r
=
N,m,u
=
1
;
while
(l
<
r){
m
=
(l
+
r)
/
2
;
son[u]
+=
k;
if
(num
<=
m){
r
=
m;
u
=
u
*
2
;
}
else
{
l
=
m
+
1
;
u
=
u
*
2
+
1
;
}
}
son[u]
+=
k;
}
int
find(
int
ith){
int
l
=
1
,r
=
N,u
=
1
,m;
while
(l
<
r){
m
=
(l
+
r)
/
2
;
if
(son[
2
*
u
+
1
]
>=
ith){
l
=
m
+
1
;
u
=
u
*
2
+
1
;
}
else
{
ith
-=
son[
2
*
u
+
1
];
r
=
m;
u
=
u
*
2
;
}
}
return
l;
}
void
init(){
int
i;
for
(i
=
1
;i
<=
N;i
++
){
pnt[i]
=
i;
v[i]
=
1
;
insert(v[i],
1
);
}
}
int
fs(
int
i){
if
(pnt[i]
==
i)
return
i;
pnt[i]
=
fs(pnt[i]);
return
pnt[i];
}
int
main(){
int
q,a,b,x,y,ith;
while
(scanf(
"
%d%d
"
,
&
N,
&
M)
!=
EOF){
init();
while
(M
--
){
scanf(
"
%d
"
,
&
q);
if
(q
==
0
){
scanf(
"
%d%d
"
,
&
a,
&
b);
x
=
fs(a);
y
=
fs(b);
if
(x
!=
y){
pnt[x]
=
y;
insert(v[x],
-
1
);
insert(v[y],
-
1
);
v[y]
+=
v[x];
insert(v[y],
1
);
}
}
else
{
scanf(
"
%d
"
,
&
ith);
printf(
"
%d\n
"
,find(ith));
}
}
}
return
0
;
}