题面在这里
题目大意:
有n个集合,每个集合有一个互不相同的元素。现在有两种操作:合并
x
,
做法:
并查集+平衡树。平衡树里维护每个集合的元素个数。
/*************************************************************
Problem: poj 2985 The k-th Largest Group
User: fengyuan
Language: C++
Result: Accepted
Time: 735 ms
Memory: 1.8 MB
Submit_Time: 2017-12-09 15:47:40
*************************************************************/
#include<cstdio>
#include<cstring>
#define rep(i, x, y) for (int i = (x); i <= (y); i ++)
#define down(i, x, y) for (int i = (x); i >= (y); i --)
#define mid ((l+r)/2)
#define lc (o<<1)
#define rc (o<<1|1)
#define pb push_back
#define mp make_pair
#define PII pair<int, int>
#define F first
#define S second
#define B begin()
#define E end()
using namespace std;
typedef long long LL;
//head
const int N = 400010;
int n, m, rt, tot;
int num[N], f[N], sz[N], cnt[N], data[N], fa[N], ch[N][2];
inline int getFa(int v){ return f[v] == v ? v : f[v] = getFa(f[v]); }
inline void pushup(int x){ sz[x] = (ch[x][0]?sz[ch[x][0]]:0) + (ch[x][1]?sz[ch[x][1]]:0) + cnt[x]; }
inline void clear(int x){ fa[x] = ch[x][0] = ch[x][1] = data[x] = sz[x] = cnt[x] = 0; }
inline void rot(int x)
{
int y = fa[x], z = fa[y];
int ff = (ch[y][1] == x);
ch[y][ff] = ch[x][ff^1]; if (ch[x][ff^1]) fa[ch[x][ff^1]] = y;
fa[x] = z; if (z) ch[z][(ch[z][1] == y)] = x;
fa[y] = x; ch[x][ff^1] = y;
pushup(y); pushup(x);
}
inline void splay(int x, int top)
{
while (fa[x] != top){
int y = fa[x], z = fa[y];
if (z != top) rot(((ch[z][0] == y) == (ch[y][0] == x)) ? y : x);
rot(x);
} if (!top) rt = x;
}
inline int find(int v)
{
int x = rt;
while (x){
if (data[x] == v){ splay(x, 0); return x; }
x = ch[x][v > data[x]];
}
}
inline int pre(int x){ x = ch[x][0]; while (ch[x][1]) x = ch[x][1]; return x; }
inline void insert(int v)
{
int x = rt;
if (!rt){
x = rt = ++ tot;
data[x] = v; sz[x] = cnt[x] = 1;
fa[x] = ch[x][0] = ch[x][1] = 0;
return;
}
while (x){
sz[x] ++; if (v == data[x]){ cnt[x] ++; break; }
int &y = ch[x][v > data[x]];
if (!y){
y = ++ tot;
data[y] = v; sz[y] = cnt[y] = 1;
fa[y] = x; ch[y][0] = ch[y][1] = 0;
x = y; break;
} x = y;
} splay(x, 0);
}
inline void del(int v)
{
int x = find(v);
if (cnt[x] > 1){ cnt[x] --; pushup(x); return; }
if (!ch[x][0] && !ch[x][1]){ clear(rt); rt = tot = 0; return; }
if (!ch[x][0]){ rt = ch[x][1]; fa[rt] = 0; return; }
if (!ch[x][1]){ rt = ch[x][0]; fa[rt] = 0; return; }
int p = pre(x), rtt = rt; splay(p, 0);
ch[rt][1] = ch[rtt][1]; fa[ch[rtt][1]] = rt;
clear(rtt); pushup(rt);
}
inline int kth(int k)
{
int x = rt;
while (x){
if (sz[ch[x][0]] < k && sz[ch[x][0]]+cnt[x] >= k) return data[x];
if (sz[ch[x][0]] >= k) x = ch[x][0];
else k -= sz[ch[x][0]]+cnt[x], x = ch[x][1];
}
}
int main()
{
scanf("%d%d", &n, &m);
rep(i, 1, n) num[i] = 1, f[i] = i, insert(1);
while (m --){
int opt, x, y, fx, fy;
scanf("%d", &opt);
if (!opt){
scanf("%d%d", &x, &y);
fx = getFa(x); fy = getFa(y);
if (fx != fy){
f[fx] = fy;
del(num[fx]); del(num[fy]);
num[fy] += num[fx];
num[fx] = 0;
insert(num[fy]);
n --;
}
} else {
scanf("%d", &x);
printf("%d\n", kth(n-x+1));
}
}
return 0;
}