#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+14;
int father[maxn];
int cnt[maxn];
int num[maxn];
int isRoot[maxn];
int N,Q;
int block;
bool cmp (int a,int b) {
return a>b;
}
void init () {
for (int i=1;i<=N;i++) {
cnt[i]=0;
num[i]=1;
father[i]=i;
isRoot[i]=1;
}
block=N;
}
int findfather (int x) {
int a=x;
while (x!=father[x]) x=father[x];
while (a!=father[a]) {
int z=a;
a=father[a];
father[z]=x;
}
return x;
}
void Union (int a,int b) {
int faA=findfather(a);
int faB=findfather(b);
if (faA==faB) {
cnt[faA]++;
return;
}
if (faA<faB) swap(faA,faB);
father[faA]=faB;
block--;
num[faB]+=num[faA];
cnt[faB]=cnt[faB]+cnt[faA]+1;
isRoot[faA]=0;
}
int getMin (int k) {
return max(1,block-k);
}
int getMax (int k) {
int ans=0;
for (int i=1;i<=N;i++)
ans+=isRoot[i]*(num[i]*(num[i]-1)/2-cnt[i]);
if (k<=ans) return block;
vector<int> vi;
for (int i=1;i<=N;i++)
if (isRoot[i]) vi.push_back(num[i]);
sort(vi.begin(),vi.end(),cmp);
k-=ans;
int ck;
for (ck=0;ck<block-1;ck++) {
k-=(vi[ck]*vi[ck+1]);
vi[ck+1]+=vi[ck];
if (k<=0) break;
}
return block-ck-1;
}
int main () {
int T;
scanf("%d",&T);
while (T--) {
scanf("%d%d",&N,&Q);
init();
int a,b;
int query;
while (Q--) {
scanf("%d",&query);
if (query==1) {
scanf("%d%d",&a,&b);
Union(a,b);
}
else {
scanf("%d",&a);
printf("%d %d\n",getMin(a),getMax(a));
}
}
}
return 0;
}
来源:https://www.cnblogs.com/zhanglichen/p/12442977.html