#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e6+14; ll father[maxn]; ll num[maxn]; ll N,Q; ll block; ll ans;//表示在当前的图下,不增加连通块数量所能增加的边数 //线段树部分 struct node { ll l,r; ll cnt;//大小为这样的连通块的数量 ll sum;//连通块的总的点数 ll pfh;//各连通块之间点数的平方和 }segTree[maxn*4]; void pushup (ll i) { segTree[i].cnt=segTree[i<<1].cnt+segTree[i<<1|1].cnt; segTree[i].sum=segTree[i<<1].sum+segTree[i<<1|1].sum; segTree[i].pfh=segTree[i<<1].pfh+segTree[i<<1|1].pfh; } void build (ll i,ll l,ll r) { segTree[i].l=l; segTree[i].r=r; if (l==r) { segTree[i].pfh=l==1?N:0; segTree[i].sum=l==1?N:0; segTree[i].cnt=l==1?N:0; return; } ll mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); pushup(i); } void update (ll i,ll t,ll b) { if (segTree[i].l==segTree[i].r) { segTree[i].cnt+=b; segTree[i].sum+=b*t; segTree[i].pfh+=b*t*t; return; } ll mid=(segTree[i].l+segTree[i].r)>>1; if (t<=mid) update(i<<1,t,b); else update(i<<1|1,t,b); pushup(i); } ll ask (ll i,ll k,ll sum) { if (segTree[i].l==segTree[i].r) { ll l=1; ll r=segTree[i].cnt; ll mid=(l+r)>>1; while (l<r) { mid=(l+r)>>1; ll tmp=mid*(mid-1)/2*segTree[i].l*segTree[i].l+mid*segTree[i].l*sum; if (tmp>=k) r=mid; else l=mid+1; } return l; } ll mid=(segTree[i].l+segTree[i].r)>>1; ll tmp=(segTree[i<<1|1].sum*segTree[i<<1|1].sum-segTree[i<<1|1].pfh)/2+segTree[i<<1|1].sum*sum; if (tmp<k) return segTree[i<<1|1].cnt+ask(i<<1,k-tmp,sum+segTree[i<<1|1].sum); else return ask(i<<1|1,k,sum); } void init () { for (int i=1;i<=N;i++) { num[i]=1; father[i]=i; } block=N; build(1,1,N); ans=0; } ll findfather (ll x) { ll a=x; while (x!=father[x]) x=father[x]; while (a!=father[a]) { ll z=a; a=father[a]; father[z]=x; } return x; } void Union (int a,int b) { ll faA=findfather(a); ll faB=findfather(b); if (faA==faB) { ans--; return; } if (faA>faB) swap(faA,faB); update(1,num[faA],-1); update(1,num[faB],-1); father[faA]=faB; block--; ans+=num[faB]*num[faA]-1; num[faB]+=num[faA]; num[faA]=0; update(1,num[faB],1); } ll getMin (ll k) { return max(1LL,block-k); } ll getMax (ll k) { if (k<=ans) return block; k-=ans; ll ck=ask(1,k,0); return block-ck+1; } int main () { int T; scanf("%d",&T); while (T--) { scanf("%lld %lld",&N,&Q); init(); ll a,b; ll query; while (Q--) { scanf("%lld",&query); if (query==1) { scanf("%lld %lld",&a,&b); Union(a,b); } else { scanf("%lld",&a); printf("%lld %lld ",getMin(a),getMax(a)); } } } return 0; }