【bzoj2280】[Poi2011]Plot 二分+倍增+二分+最小圆覆盖
题目描述
给出一系列点p_1, p_2, ... , p_n,将其分成不多余m个连续的段,第i段内求一个点q_i,使得q_i到这段内点的距离的最大值的最大值最小
输入
第一行,n m
下面n行,每行两个整数,表示p_i的x y坐标
1<=m<=n<=100000
坐标范围[-1000000,1000000] 0<p,q,r<=150,输入中至少包含一个’N’
输出
第一行,q_i到这段内点的距离的最大值的最大值的最小值
第二行,分成的段数k
下面k行,每行两个实数,表示q_k的x y坐标
All the real numbers should be printed with at most 15 digits after the decimal point.
样例输入
7 2
2 0
0 4
4 4
4 2
8 2
11 3
14 2
样例输出
3.00000000
2
2.00000000 1.76393202
11.00000000 1.99998199
题解
二分+倍增+二分+最小圆覆盖
最大值最小,一眼二分答案。
考虑怎么判定:取前任意个点跑最小圆覆盖,直到半径大于mid为止,最后看分成段的数目是否超过m即可。
然而这样暴力跑是不行的,需要优化这个过程;同时直接再二分也是不可取的,因为二分的区间长度是满的,最坏情况下每段长度都为1,每段都需要$O(n\log n)$的时间来找,GG。
所以需要让求最小圆覆盖的点数只与每段长有关。考虑倍增,处理出第一个$j$,满足$2^j$个不满足条件。然后在$2^{j-1}$到$2^j$之间二分处理即可。这样第一部分时间复杂度为$O(len)$,第二部分时间复杂度为$O(len\log len)$,与n无关,所以可以满足时间要求。
因此总的时间复杂度为$O(n\log^2n)$,然而常数巨大。。。所以才给300s。。。
最小圆覆盖的求法参见 http://www.cnblogs.com/GXZlegend/p/7467029.html
CQzhangyu说卡精度,然而没看出来= = 1A了
#include <cstdio>
#include <algorithm>
#define N 100010
#define eps 1e-15
using namespace std;
int n , m , id[N] , tot;
double mid , x[N] , y[N] , ansx[N] , ansy[N];
inline double squ(double x)
{
return x * x;
}
bool check(int lp , int rp , double &vx , double &vy)
{
int i , j , k , len = rp - lp + 1;
double px = 0 , py = 0 , r = 0 , x1 , x2 , x3 , y1 , y2 , y3;
for(i = lp ; i <= rp ; i ++ ) id[i - lp + 1] = i;
random_shuffle(id + 1 , id + len + 1);
for(i = 1 ; i <= len ; i ++ )
{
if(squ(px - x[id[i]]) + squ(py - y[id[i]]) > r + eps)
{
px = x[id[i]] , py = y[id[i]] , r = 0;
for(j = 1 ; j < i ; j ++ )
{
if(squ(px - x[id[j]]) + squ(py - y[id[j]]) > r + eps)
{
px = (x[id[i]] + x[id[j]]) / 2 , py = (y[id[i]] + y[id[j]]) / 2 , r = (squ(x[id[i]] - x[id[j]]) + squ(y[id[i]] - y[id[j]])) / 4;
if(r > mid * mid + eps) return 0;
for(k = 1 ; k < j ; k ++ )
{
if(squ(px - x[id[k]]) + squ(py - y[id[k]]) > r + eps)
{
x1 = x[id[i]] , x2 = x[id[j]] , x3 = x[id[k]];
y1 = y[id[i]] , y2 = y[id[j]] , y3 = y[id[k]];
px = (x1 * x1 * (y2 - y3) + x2 * x2 * (y3 - y1) + x3 * x3 * (y1 - y2) - (y1 - y2) * (y2 - y3) * (y3 - y1)) / (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2;
py = ((x1 - x2) * (x2 - x3) * (x3 - x1) - y1 * y1 * (x2 - x3) - y2 * y2 * (x3 - x1) - y3 * y3 * (x1 - x2)) / (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2;
r = squ(px - x1) + squ(py - y1);
if(r > mid * mid + eps) return 0;
}
}
}
}
}
}
vx = px , vy = py;
return 1;
}
bool judge()
{
int i , len , last , l , r , mid;
bool flag;
double tmpx , tmpy;
tot = 0;
for(i = 1 ; i <= n ; i = last + 1)
{
if(tot == m) return 0;
flag = 0;
for(len = 1 ; !flag ; len <<= 1)
{
if(!check(i , min(i + len - 1 , n) , tmpx , tmpy))
{
flag = 1;
break;
}
else if(i + len - 1 >= n)
{
tot ++ , ansx[tot] = tmpx , ansy[tot] = tmpy;
return 1;
}
l = i + len;
}
r = min(i + len - 1 , n) , last = l - 1;
while(l <= r)
{
mid = (l + r) >> 1;
if(check(i , mid , tmpx , tmpy)) last = mid , l = mid + 1;
else r = mid - 1;
}
check(i , last , tmpx , tmpy) , tot ++ , ansx[tot] = tmpx , ansy[tot] = tmpy;
}
return 1;
}
int main()
{
srand(20011011);
int i , cnt = 50;
double l = 0 , r = 2e6;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) scanf("%lf%lf" , &x[i] , &y[i]);
while(cnt -- )
{
mid = (l + r) / 2;
if(judge()) r = mid;
else l = mid;
}
printf("%.15lf\n" , r);
mid = r , judge();
printf("%d\n" , tot);
for(i = 1 ; i <= tot ; i ++ ) printf("%.15lf %.15lf\n" , ansx[i] , ansy[i]);
return 0;
}
【bzoj2280】[Poi2011]Plot 二分+倍增+二分+最小圆覆盖的更多相关文章
- BZOJ2280 [Poi2011]Plot 二分+倍增+最小圆覆盖
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2280 https://loj.ac/problem/2159 题解 显然对于一段的 \(q_i ...
- BZOJ2280 [Poi2011]Plot
恩..这题真是sxbk 我们先二分答案,然后判断答案是否满足要求 判断方法是二分当前段的长度一直做到底,当然我们可以用倍增这样快一点,直接随机增量就可以了 然后就是卡常..... 然后就是卡精度QAQ ...
- 【做题】POI2011R1 - Plot——最小圆覆盖&倍增
原文链接 https://www.cnblogs.com/cly-none/p/loj2159.html 题意:给出\(n\)个点,你需要按编号将其划分成不超过\(m\)段连续的区间,使得所有每个区间 ...
- ACM-ICPC Beijing 2016 Genius ACM(倍增+二分)
描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数,如果 S 中的整 数不够 M 对,则取到不能取为止),使 ...
- 【题解】我也不是B ifrog 1112 二分 倍增
题目传送门:http://ifrog.cc/acm/problem/1112 神奇的倍增二分,长见识了,在此做个记录,分享给大家. 懒得写题解了,直接转YJQ的:http://ifrog.cc/acm ...
- poj3579 二分套二分
和poj3685类似,都是二分答案然后在判断时再二分 这题的内层二分可以用stl代替 /* 二分套二分,思路:升序排序数据,先二分答案x进行判断,判断时枚举每个元素,二分找到和其之差小于等于x的所有值 ...
- LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配
#2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- POJ-3579 Median---二分第k大(二分套二分)
题目链接: https://cn.vjudge.net/problem/POJ-3579 题目大意: 求的是一列数所有相互之间差值的序列的最中间的值是多少. 解题思路: 可以用二分套二分的方法求解第m ...
- poj 3579 Median 二分套二分 或 二分加尺取
Median Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5118 Accepted: 1641 Descriptio ...
随机推荐
- 【洛谷4657】[CEOI2017] Chase(一个玄学的树形DP)
点此看题面 大致题意: 有一棵树,树上编号为\(i\)的节点上有\(F_i\)个铁球,逃亡者有\(V\)个磁铁,当他在某个节点放下磁铁时,与这个节点相邻的所有节点上的铁球都会被吸引到这个节点.然后一个 ...
- 破解 D-H 协议
756: 破解 D-H 协议 时间限制: 1 Sec 内存限制: 128 MB提交: 78 解决: 18[提交] [状态] [讨论版] [命题人:admin] 题目描述 Diffie-Hellma ...
- 关于SQL数据库 msdb.dbo.sp_send_dbmail 函数发送邮件的场景分析
关于SQL数据库 msdb.dbo.sp_send_dbmail 函数发送邮件的场景分析 在推行系统中,时不时会有用户提出希望系统能自动推送邮件,由于手头的工具和能力有限,不少需求都借助于sql se ...
- Mysql--select基础查询
基本语法:select 查询列表 from 表名 查询列表可以是表中字段.常量值.表达式.函数:查询的结果是一个虚拟的表格. 注意: ①sql语言大小写不敏感 ②关键字不能分行或略写 ③一般书写方式为 ...
- django+xadmin在线教育平台(五)
3-3 django orm介绍与model设计 上节教程完成后代码(来学习本节前置条件): 对应commit: 留言板前端页面展示.本次内容截止教程3-2结束. 可能现在你还在通过手写sql语句来操 ...
- vue-cli的build的文件夹下没有dev-server.js文件,怎么配置mock数据
因为最新版本的vue-cli已经放弃dev-server.js,只需在webpack.dev.conf.js配置就行 新版webpack.dev.conf.js配置如下: 在const portfin ...
- [Wolfgang Mauerer] 深入linux 内核架构 第十三章 系统调用
作为Linux开发爱好者,从事linux 开发有三年多时间.做过bsp移植,熟悉u-boot代码执行流程:看过几遍<linux 设备驱动程序开发>,分析过kernel启动流程,写过驱动,分 ...
- LeetCode951-翻转等价二叉树
问题:翻转等价二叉树 我们可以为二叉树 T 定义一个翻转操作,如下所示:选择任意节点,然后交换它的左子树和右子树. 只要经过一定次数的翻转操作后,能使 X 等于 Y,我们就称二叉树 X 翻转等价于二叉 ...
- Nginx配置根据客户端设备转发
#user nobody; worker_processes ; #error_log logs/error.log; #error_log logs/error.log notice; #error ...
- h5中的video与audio
·首先带大家熟悉一下video标签的属性方法,根据属性方法做一个小demo, HTML5支持的视频格式: Ogg 带有Theora视频编码+Ogg文件 支持的浏览器:F.O MEPG4 带有H.26 ...