现在有一个没有边的简单无向图(图中只有一些孤立的顶点),顶点的标号从1开始。对图可以执行以下两种操作: 1 a b——用一条边连接两个顶点a和b。确保在执行此操作之前,两个顶点a和b之间没有直接连接的边。
2 k——一个查询的结果:在图中添加k条边后,连接的两个部分可能的最小数量和最大数量。注意,在添加k条边后,该图必须仍然是简单图,并且查询操作不会改变图。 请求出第二种操作的结果。简单图表示没有自循环和多重边。
输入格式:
有多组测试数据。第一行输入一个整数,表示测试数据的组数T。
对每组测试数据有:
第一行包含两个整数,分别表示顶点数n和操作数q(1≤n≤105,1≤q≤2×105)。
接下来的行中,每行第一个整数表示操作的种类。
- 如果后面有两个整数ai和bi,(1≤ai,bi≤n,ai≠bi),表示是第一种操作。并且确保在执行此操作之前,两个顶点之间没有直接连接的边。
- 如果后面有一个整数ki(0≤ki≤2n(n−1)),表示是第二种操作。并且确保在添加ki条边后,图仍然有可能是一个简单图。这些测试数据保证n的数量不超过106,q的数量不超过2×106。
输出格式:
对第二种类型的每个操作,输出一行包括两个用空格分开的整数,分别表示在这个查询中,两部分之间可能连接的最小数量和最大数量。
输入样例:
在这里给出一组输入。例如:
1
5 5
1 1 2
2 1
1 1 3
2 1
2 3
输出样例:
在这里给出相应的输出。例如:
3 3
2 3
1 2
#include<bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
int n,q,cnt,f[MAX];
ll tot_ret,ret[MAX],num[MAX];
int getf(int v)
{
return f[v] == v ? v : f[v] = getf(f[v]);
}
struct TREE
{
int l,r;
ll cnt,sum;
ll pfh;
} tree[MAX<<2];
void pushup(int cur)
{
tree[cur].cnt = tree[cur*2].cnt + tree[cur*2+1].cnt;
tree[cur].sum = tree[cur*2].sum + tree[cur*2+1].sum