[ABC372E] K-th Largest Connected Components

题意

给出 \(q\) 个操作。

  1. \(u\)\(v\) 连边。
  2. \(u\) 所在的连通块中编号第 \(k\) 大的点。

思路

连通块很容易想到并查集,求第 \(k\) 大可以用平衡树(虽然赛时没看到 \(k\le 10\)),合并时将信息从将小的连通块合并到大的连通块,这样可以减少时间复杂度。
什么?你不会写平衡树?直接套 pbds 库中的 tree 就可以了(具体见代码)。

代码

#include<bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;//注意使用pbds库时需要加上头文件和命名空间
struct bal_tree{
	tree<int,null_type,less_equal<int>,rb_tree_tag,tree_order_statistics_node_update> t;//使用tree的方式,具体参数可以上网查,不会的直接复制就可以了
	void insert(int x){t.insert(x);}
	void del(int x){t.erase(t.upper_bound(x));}
	int rnk(int x){return t.order_of_key(x)+1;}
	int find_rnk(int x){return *t.find_by_order(x-1);}
	int upper_bound(int x){return *t.upper_bound(x);}
	int lower_bound(int x){return *t.lower_bound(x);}
}t[200005]; 
int n,q,f[200005];
int find(int x){
	if(f[x]!=x) f[x]=find(f[x]);
	return f[x];
}
signed main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++)
		f[i]=i,t[i].insert(i);
	while(q--){
		int op,x,y;
		cin>>op>>x>>y;
		if(op==1){
			int p1=find(x),p2=find(y);
			if(p1!=p2){
				if(t[p1].t.size()>t[p2].t.size())
					swap(p1,p2);
				f[p1]=p2;
				for(int v:t[p1].t)
					t[p2].insert(v);
				t[p1].t.clear();
			}
		}
		else{
			x=find(x);
			if(t[x].t.size()<y)
				cout<<-1<<endl;
			else
				cout<<t[x].find_rnk(t[x].t.size()-y+1)<<endl;//注意是第k大
		}
	}
	return 0;
}
posted @ 2024-09-23 15:41  WuMin4  阅读(23)  评论(0)    收藏  举报