题干:

DreamGrid has just found an undirected simple graph with  vertices and no edges (that's to say, it's a graph with  isolated vertices) in his right pocket, where the vertices are numbered from 1 to . Now he would like to perform  operations of the following two types on the graph:

  • 1 a b -- Connect the -th vertex and the -th vertex by an edge. It's guaranteed that before this operation, there does not exist an edge which connects vertex  and  directly.
  • 2 k -- Find the answer for the query: What's the minimum and maximum possible number of connected components after adding  new edges to the graph. Note that after adding the  edges, the graph must still be a simple graph, and the query does NOT modify the graph.

Please help DreamGrid find the answer for each operation of the second type. Recall that a simple graph is a graph with no self loops or multiple edges.

Input

There are multiple test cases. The first line of the input is an integer , indicating the number of test cases. For each test case:

The first line contains two integers  and  (, ), indicating the number of vertices and the number of operations.

For the following  lines, the -th line first contains an integer  (), indicating the type of the -th operation.

  • If , two integers  and  follow (, ), indicating an operation of the first type. It's guaranteed that before this operation, there does not exist an edge which connects vertex  and  directly.
  • If , one integer  follows (), indicating an operation of the second type. It's guaranteed that after adding  edges to the graph, the graph is still possible to be a simple graph.

It's guaranteed that the sum of  in all test cases will not exceed , and the sum of  in all test cases will not exceed .

Output

For each operation of the second type output one line containing two integers separated by a space, indicating the minimum and maximum possible number of connected components in this query.

Sample Input

1
5 5
1 1 2
2 1
1 1 3
2 1
2 3

Sample Output

3 3
2 3
1 2

解题报告:

以连通块中元素个数为权值,建立线段树,维护三个变量,分别是cnt(这样的连通块的数量),sum(连通块的总的点数),pfh(各连通块之间点数的平方和)(注意不是和的平方)

cnt代表连通块数量,tot_ret代表当前状态下的图,在不增长连通块个数的前提下,可以加的边数。

所以对于最小值很显然。

对于最大值,首先减去块内连的边,然后去线段树查询剩下的边怎么加,首先填连通块元素大小大的,这样也就是类似查询第k大,查到叶子结点,再判断 块中元素为tree[cur].l的 块 我需要多少个 返回回去,就行了。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
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;tree[cur].pfh = tree[cur*2].pfh + tree[cur*2+1].pfh;
}
void build(int l,int r,int cur) {tree[cur].l=l;tree[cur].r=r;if(l == r) {tree[cur].pfh = tree[cur].sum = tree[cur].cnt = (l==1?n:0);return;}int mid = (l+r)>>1;build(l,mid,cur*2);build(mid+1,r,cur*2+1);pushup(cur);
}
void update(int cur,ll tar,ll val) {if(tree[cur].l == tree[cur].r) {tree[cur].cnt += val;// 连通块元素数量为tar的连通块的数量。 tree[cur].sum += val*tar;tree[cur].pfh += val*tar*tar;return;}int mid = (tree[cur].l+tree[cur].r)>>1;if(tar<=mid) update(cur*2,tar,val);else update(cur*2+1,tar,val); pushup(cur);
}
ll query(int cur,ll k,int sum) {if(tree[cur].l == tree[cur].r) {ll l=1,r=tree[cur].cnt,mid;mid=(l+r)>>1;while(l<r) {mid=(l+r)>>1;if(mid*(mid-1)/2*tree[cur].l*tree[cur].l + mid*tree[cur].l*sum >= k) r=mid;else l = mid+1;}return l;}int mid = (tree[cur].l+tree[cur].r)>>1;ll tmp = (tree[cur*2+1].sum * tree[cur*2+1].sum - tree[cur*2+1].pfh)/2 + tree[cur*2+1].sum * sum ;if(tmp < k)return tree[cur*2+1].cnt + query(cur*2,k-tmp,sum+tree[cur*2+1].sum);else return query(cur*2+1,k,sum);
}
ll cal(ll k) {if(k<=tot_ret) return cnt;k-=tot_ret;ll tmp = query(1,k,0);return cnt-tmp+1;
}
int main()
{int t;cin>>t;while(t--) {scanf("%d%d",&n,&q);for(int i = 1; i<=n; i++) f[i] = i,num[i] = 1,ret[i] = 0;tot_ret=0,cnt=n;//cnt记录连通块数 build(1,n,1);while(q--) {int op;scanf("%d",&op);if(op == 1) {int a,b;scanf("%d%d",&a,&b);a=getf(a),b=getf(b);if(a==b) {ret[a]--;tot_ret--;continue;}if(num[a] > num[b]) swap(a,b);//让b是边多的update(1,num[a],-1);update(1,num[b],-1);f[a]=b;//按秩合并到大集合tot_ret += num[a]*num[b]-1;cnt--;ret[b]=ret[a]+ret[b] + num[a]*num[b]-1;num[b]+=num[a];ret[a]=num[a]=0;update(1,num[b],1);         }else {ll k;scanf("%lld",&k);ll minn = max(1LL,cnt-k);ll maxx = cal(k);printf("%lld %lld\n",minn,maxx);}          }}return 0 ;
}

【2019浙江省赛 - A】Vertices in the Pocket(权值线段树下二分,图,思维)相关推荐

  1. 2019CCPC网络赛 1002 HDU 6703(权值线段树)

    2019CCPC网络赛 1002 HDU 6703(权值线段树) 思路:用权值线段树存题目给的数据后,2操作就是求权值线段树中大于等于k的部分中,靠近左端点的第一个大于r的值(这个求出来的只是原序列中 ...

  2. JZOJ 7036. 2021.03.30【2021省赛模拟】凌乱平衡树(平衡树单旋+权值线段树)

    JZOJ 7036. 2021.03.30[2021省赛模拟]凌乱平衡树 题目大意 给出两棵Treap,大小分别为 n , m n,m n,m,每个点的 p r i o r i t y priorit ...

  3. 2019牛客多校第七场E Find the median 权值线段树+离散化

    Find the median 题目链接: https://ac.nowcoder.com/acm/contest/887/E 题目描述 Let median of some array be the ...

  4. jzoj5986. 【WC2019模拟2019.1.4】立体几何题 (权值线段树)

    传送门 题面 题解 不难看出每个点的大小为行列限制中较小的那一个(因为数据保证有解) 对于行的每个限制,能取到的个数是列里限制大于等于它的数的个数,同理,对于列是行里大于它的个数(这里没有等于,为了避 ...

  5. 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)

    传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...

  6. 2019暑期训练——牛客第七场 C. Governing sand(权值线段树)

    Governing sand 链接: https://ac.nowcoder.com/acm/contest/887/C 题意: 给n种树,其中每一种树都有高度h,每砍掉一棵树所需要的代价c,这种树的 ...

  7. 计蒜客 2020 蓝桥杯省赛 B 组模拟赛(五)E区间dp H 裴蜀 J dp A-J 权值线段树

    题目链接 因为要去笔试.所以只打了两个小时,有点求快,很多细节没写好就匆匆交,而且没有检查,打的有点菜 C-煎牛排 做法: 所有的面的个数sum=2*n   然后sum/(2*k)即可. ans=ma ...

  8. 2019 浙江省赛部分题解(The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple)

    签到题 GLucky 7 in the Pocket Time Limit: 1 Second      Memory Limit: 65536 KB BaoBao loves number 7 bu ...

  9. ICPC2017网络赛(南宁)子序列最大权值(树状数组+dp)

    https://nanti.jisuanke.com/t/17319 Let SS be a sequence of integers s_{1}s ​1 ​​ , s_{2}s ​2 ​​ , .. ...

最新文章

  1. CoreText入坑一
  2. 计算机c语言循环作业,C语言计算机作业编程.doc
  3. 将会改变未来IT世界的十种编程语言
  4. 工作五年,后面四年重复着第一年的活儿?
  5. Java黑皮书课后题第5章:*5.46(倒排一个字符串)编写一个程序,提示用户输入一个字符串,然后以反序显示该字符串
  6. 为or、in平反——or、in到底能不能利用索引?
  7. CentOS 7 Linux 的初始化系统(系统服务管理和控制程序/Init System) -- systemd 详解
  8. STM32——PID恒温控制
  9. C语言中二维数组名与数组地址、首行地址、首行首元素地址关系与区别详解(初学者必须掌握)
  10. 《计算机网络:自顶向下方法(原书第6版)》一2.7 TCP套接字编程
  11. EJB3.0高速入门项目开发步骤
  12. Spring使用Cache、整合Ehcache
  13. linux中了minerd之后完全清理过程
  14. ios kb转m_字节、kb、M怎么换算
  15. Pytorch实战——知识点记录(一)
  16. 运维工程师项目案例_要建设AIOps,运维工程师的角色和职责需如何调整?
  17. 【docker详解02】-docker安装
  18. 【复盘】如何写一份教程?
  19. 从一线城市回家工作的体验
  20. 关于Unity发布的WebGL项目出现问题的解决方法和本地网站部署

热门文章

  1. Js实现异步刷新(原创)
  2. 基于三值图像的车牌识别测试程序发布
  3. 流量专家为114搜索提供权威流量访问统计
  4. [Leetcode][第106题][JAVA][ 从中序与后序遍历序列构造二叉树][分治][递归]
  5. c语言获取dll文件路径,C语言URLDownloadToFile获取文件下载进度
  6. c++ stack 遍历_划重点啦!带你解读图的两种遍历方式
  7. 量子计算机如何确定量子状态,量子计算机六个量子位足以确定三个简单分子的基态...
  8. 北方股份无人驾驶矿卡_踏歌智行完成B轮2亿元融资,无人驾驶矿山赛道爆发在即...
  9. openssl-1.0.1e for arm
  10. 编译pjsip2.1.0 vidgui程序时,xlib保错问题