ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集
正赛的时候完全没看这个题,事后winterzz告诉我他想出来的解法。
首先题意是给出n个点,m次操作。
操作有一种是连接两个点,另一种是求此时再为这个图连k条边,最少和最多能有几个联通块。
最少的求法很简单,显然一条边可以减少一个联通块。
最多的求法则稍微复杂:
首先我们先将所有联通块填成完全图,这部分边是白给的。
接下来最优的连接方式显然是将最大的和次大的联通块合并,如果还有边需要连就再将其把第三大的联通块合并...一直这样下去。
这个东西我们显然可以二分,二分出将多少个联通块合并成一起能用完k个边。
winterzz表示可以splay搞搞,只要支持插入一个点和求后缀和就可以了。
但是仔细想想,其实我们用线段树也可以做到这个二分。
我们做一个权值线段树来维护大小为k的块的个数,和它们的可容纳边总和,与它们的点个数总和,然后在这个线段树上二分。
但是这样我们二分到子叶节点k就不知道要合并掉多少个大小为k的块了,所以我们在子叶节点再做一次二分即可,这样复杂度仍然只有一个log,因为每次查询我们只会到一个子叶节点。
以下附上代码:
#include<bits/stdc++.h>
using namespace std;
#define mid (l+r)/2
int i,i0,n,m,T,pre[100005],siz[100005];
long long sum,num;
int fin(int x){return (pre[x]==x)?x:pre[x]=fin(pre[x]);}
void uni(int x,int y){if(fin(x)!=fin(y))pre[fin(y)]=fin(x);}
struct node
{
long long siz,siz2,siz3;
}tree[400005];
node operator+(node a,node b){return {a.siz+b.siz,a.siz2+b.siz2,a.siz3+b.siz3};}
void b_tree(int l,int r,int p)
{
if(l==r&&l==1)tree[p].siz=tree[p].siz3=n,tree[p].siz2=0;
else tree[p].siz=tree[p].siz2=tree[p].siz3=0;
if(l!=r)b_tree(l,mid,p*2),b_tree(mid+1,r,p*2+1);
}
void add_tree(int l,int r,int p,int a)
{
if(l==r)tree[p].siz+=l,tree[p].siz2+=l*(l-1)/2,tree[p].siz3++;
else
{
if(a<=mid) add_tree(l,mid,p*2,a);
else if(a>=mid+1)add_tree(mid+1,r,p*2+1,a);
tree[p]=tree[p*2]+tree[p*2+1];
}
}
void erase_tree(int l,int r,int p,int a)
{
if(l==r)tree[p].siz-=l,tree[p].siz2-=l*(l-1)/2,tree[p].siz3--;
else
{
if(a<=mid) erase_tree(l,mid,p*2,a);
else if(a>=mid+1)erase_tree(mid+1,r,p*2+1,a);
tree[p]=tree[p*2]+tree[p*2+1];
}
}
int q_tree(int l,int r,int p,long long k,long long v)
{
if(l==r)
{
int ll=1,rr=tree[p].siz3;
while(ll<rr)
{
int mmid=(ll+rr)/2;
if((v+mmid*l)*(v+mmid*l-1)/2>=l*(l-1)/2*mmid+k)rr=mmid;
else ll=mmid+1;
}
return ll;
}
else
{
if((v+tree[p*2+1].siz)*(v+tree[p*2+1].siz-1)/2>=k+tree[p*2+1].siz2)return q_tree(mid+1,r,p*2+1,k,v);
else return q_tree(l,mid,p*2,k+tree[p*2+1].siz2,v+tree[p*2+1].siz)+tree[p*2+1].siz3;
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)pre[i]=i,siz[i]=1;
sum=0,num=n;
b_tree(1,n,1);
for(i=1;i<=m;i++)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,y;
scanf("%d %d",&x,&y);
if(fin(x)!=fin(y))
{
erase_tree(1,n,1,siz[fin(x)]),erase_tree(1,n,1,siz[fin(y)]);
sum-=siz[fin(x)]*(siz[fin(x)]-1)/2,sum-=siz[fin(y)]*(siz[fin(y)]-1)/2;
siz[fin(x)]=siz[fin(x)]+siz[fin(y)],sum+=siz[fin(x)]*(siz[fin(x)]-1)/2;
add_tree(1,n,1,siz[fin(x)]),uni(x,y);
num--;
}
sum--;
}
else
{
long long k;
scanf("%lld",&k);
printf("%lld %lld\n",max(1ll,(num-k)),num+1-q_tree(1,n,1,k-sum,0));
}
}
}
return 0;
}
ZOJ 4100 浙江省第16届大学生程序设计竞赛 A题 Vertices in the Pocket 线段树+并查集的更多相关文章
- ZOJ 4103 浙江省第16届大学生程序设计竞赛 D题 Traveler 构造
这个题,正赛的时候也没有过,不过其实已经有了正确的解法,可惜时间不多了,就没有去尝试. 题意是有n个点,i点能通向i-1,然后i和i*2.i*2+1互通. 请你构造一种路径从1能走完所有点,并且不重复 ...
- ZZUOJ-1195-OS Job Scheduling(郑州大学第七届ACM大学生程序设计竞赛E题)
1195: OS Job Scheduling Time Limit: 2 Sec Memory Limit: 128 MB Submit: 106 Solved: 35 [id=1195&quo ...
- angry_birds_again_and_again(2014年山东省第五届ACM大学生程序设计竞赛A题)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2877 题目描述 The problems ca ...
- 湖南省第六届大学生程序设计大赛原题 F Biggest Number (UVA1182)
Biggest Number http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30851#problem/F 解题思路:DFS(检索)+BF ...
- 黑龙江省第七届大学生程序设计竞赛-Mysterious Organization
描述 GFW had intercepted billions of illegal links successfully. It has much more effect. Today, GFW i ...
- 黑龙江省第七届大学生程序设计竞赛-Heap
描述 A heap is a full binary tree; for each node, its key is greater than its two sub-node’s key. Two ...
- 《内蒙古自治区第十三届大学生程序设计竞赛试题_H 公孙玉龙》
这个题有点小坑,最坑的地方就是 输入的b 变量 有可能 是 负数 ! 负数 ! 负数! 对 ,你没有看错,就是负数,坑死我了, 一直都是 content.charAt(0) 判断 ...
- 浙江财经大学第十五届大学生程序设计竞赛------B 烦恼先生打麻将
问题 B: B - 烦恼先生打麻将 时间限制: 1 Sec 内存限制: 256 MB提交: 8 解决: 5[提交][状态][讨论版] 题目描述 输入 6 6 Z D 1S 1S 9W 5W 2S ...
- River Crossing---河南省第六届大学生程序设计竞赛
题目描述 Afandi is herding N sheep across the expanses of grassland when he finds himself blocked by a ...
随机推荐
- Linux常用基本命令wc-统计文件的字节,字符,行数
wc命令 作用:统计文件的字节,单词,行数 用法:wc [option] [file] -c:统计字节 ghostwu@dev:~/linux/uniq$ cat ghostwu.txt 192.16 ...
- python 字符串与列表的相互转换 数据类型转换
Python数据类型之间的转换 函数 描述 int(x [,base]) 将x转换为一个整数 long(x [,base] ) 将x转换为一个长整数 float(x) 将x转换到一个浮点数 compl ...
- jQuery通用的全局遍历方法$.each()用法实例
1.jQuery通用的全局遍历方法$.each()用法 2. test.json文件代码: 3. html代码 4.jQuery代码 <script src="jquery-1.3.1 ...
- 【读书笔记】iOS-iOS定位
iOS提供3种不同的定位途径: 1,WiFi定位,通过查询一个WiFi路由器的地理位置信息,比较省电:iPhone,iPod touch和iPad都可以采用: 2,蜂窝式移动电话基站定位,通过移动运营 ...
- element-ui 中的table的列隐藏问题
element-ui 中的table和bootstrap中的table的某些设置还是有一定的差别的.之前用bootstrap做的表格,想要实现简短列和详细列的切换.因为详细列实在有太多列了,拉动滚动条 ...
- ActiveReports 报表控件V12新特性 -- RPX报表转换为RDL报表
ActiveReports是一款专注于 .NET 平台的报表控件,全面满足 HTML5 / WinForms / ASP.NET / ASP.NET MVC / WPF 等平台下报表设计和开发工作需求 ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 12(The End)
Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 11------------------- 现在,我们希望从 " ...
- DOS中的ECHO命令详解
1. 作为控制批处理命令在执行时是否显示命令行自身的开关 格式:ECHO [ON|OFF] 如果想关闭“ECHO OFF”命令行自身的显示,则需要在该命令行前加上“@”. 2. 显示当前ECHO ...
- 新知食APP架构分析--北京识物科技有限公司旗下产品
俗话说不打无准备之仗,这次真是有点懵逼了,建议大家去面试的时候,尤其是去小型互联网公司的时候,如果你想比其他人有竞争力,那么你要研究一下当前他的公司正在开发产品,他们的业务类型是什么样的,比如他们公司 ...
- Loadrunner打开VU时候报错Critical error(cannot use Exceptiondialog)
打开Loadrunner打开VU时候报错Critical error(cannot use Exceptiondialog) 卸载后,删掉注册表,重新安装,打开还是这样 怎么办呢 我男票告诉我,从开始 ...