题意:
。。。
思路:
用一个数据结构来存所有树的大小,合并操作先消去旧的再插入新的大小。
可以用 treap, BIT等等。。
这里有个树状数组
O(logn)
查询的方法,没能看懂。。
const int N = 200000 + 5;
typedef long long LL;
namespace Treap {
static const int MaxNode = N;
int root, nodes, key[MaxNode], fix[MaxNode],
ch[MaxNode][2], cnt[MaxNode], siz[MaxNode];
void init() {
root = 0;
nodes = 1;
fix[0] = INT_MAX;
siz[0] = 0;
}
inline void update(int x) {
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
}
void rot(int& x, int t) {
int y = ch[x][t];
ch[x][t] = ch[y][1^t];
ch[y][1^t] = x;
update(x);
update(y);
x = y;
}
void insert(int& x, int k) {
if ( x ) {
if ( key[x] == k ) {
++ cnt[x];
} else {
int t = key[x] < k;
insert(ch[x][t], k);
if ( fix[ch[x][t]] < fix[x] ) {
rot(x, t);
}
}
} else {
x = nodes ++;
key[x] = k;
cnt[x] = 1;
fix[x] = rand();
ch[x][0] = ch[x][1] = 0;
}
update(x);
}
void erase(int& x, int k) {
if ( key[x] == k ) {
if ( cnt[x] > 1 ) {
-- cnt[x];
} else {
if ( !ch[x][0] && !ch[x][1] ) {
x = 0;
return;
} else {
int t = fix[ch[x][0]] > fix[ch[x][1]];
rot(x, t);
erase(ch[x][1^t], k);
}
}
} else {
int t = key[x] < k;
if ( ch[x][t] ) erase(ch[x][t], k);
}
update(x);
}
int count(int x, int k) {
if ( x ) {
if ( key[x] == k )
return cnt[x];
else
return count( ch[x][key[x] < k], k );
} else
return 0;
}
int getKth(int x, int k) {
if ( k <= siz[ch[x][0]] )
return getKth(ch[x][0], k);
k -= siz[ch[x][0]] + cnt[x];
if ( k <= 0 )
return key[x];
if ( k <= siz[ch[x][1]] )
return getKth(ch[x][1], k);
else
throw runtime_error("this is no kth element");
}
};
namespace UF {
int pa[N], sz[N];
int Find(int x) { return x == pa[x] ? x : pa[x] = Find(pa[x]); }
void init(int n) {
Treap::init();
rep(i, 1, n) pa[i] = i, sz[i] = 1;
rep(i, 1, n) Treap::insert(Treap::root, 1);
}
void Union(int x, int y) {
int px = Find(x), py = Find(y);
if ( px != py ) {
Treap::erase(Treap::root, sz[px]);
Treap::erase(Treap::root, sz[py]);
sz[px] += sz[py];
pa[py] = px;
Treap::insert(Treap::root, sz[px]);
#if 0
cout << "after merge" << endl;
int tot = tree.siz[tree.root];
rep(i, 1, tot) cout << tree.getKth(tree.root, i) << ' '; cout << endl;
#endif // 1
}
}
int query(int k) {
int tot = Treap::siz[Treap::root];
try {
return Treap::getKth(Treap::root, tot + 1 - k);
} catch ( exception& e ) {
return 1;
}
//return tree.getKth(tree.root, tot + 1 - k);
}
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
int n, m;
scanf("%d%d", &n, &m);
UF::init(n);
int op, x, y;
rep(i, 1, m) {
scanf("%d", &op);
if ( op == 0 ) {
scanf("%d%d", &x, &y);
//cout << "merge " << x << ' ' << y << endl;
UF::Union(x, y);
} else {
scanf("%d", &x);
//cout << "query " << x << endl;
printf("%d\n", UF::query(x));
}
}
return 0;
}