直接来构造。

考虑扫描线。从左到右扫,考虑当前扫到了一个左端点,我们把这个左端点连到其他点上。

我们可以找到这个点下方离他最近的线段,并且记下每条线段上方在扫描线左侧且最靠右,与这条线段中间没有其他线段的点,然后直接把左端点连到这样的点上就行了。容易证明这样的连发一定是对的。

找线段的过程用一个\(\text{set}\)来维护,对于每条线段记一个最后出现的在这条线段。

对于一些不好分类讨论的特殊情况,我们可以在所有线段的最下方加上一条直线,然后因为可能有斜率不存在的线段,我们可以把所有点随机旋转一下。就做完了

#include <cstdio>
#include <iostream>
#include <cmath>
#include <set>
#include <algorithm>
#define LL long long
#define db long double
using namespace std;
inline int read() {
int res = 0, flag = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') flag = 1;
for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48);
if(flag) res = ~res + 1; return res;
}
const db t = 1007.0/1009.0, cost = cos(t), sint = sin(t);
const db inf = 1e10;
const int N = 1e5 + 10;
int n;
struct Point {
int id;
db x, y;int rx, ry;
inline void get() {x = rx * cost - ry * sint, y = ry * cost + rx * sint;}
inline void print() {printf("%d %d ",rx,ry);}
inline void print1() {printf("%Lf %Lf ",x,y);}
inline bool operator < (const Point y) const{return (x < y.x);}
}p[N << 1], q[N << 1];
db nx;
struct Segment {
int l, r; mutable int lst; db k, b;
inline void get() {k = (p[l].y - p[r].y) / (p[l].x - p[r].x), b = p[l].y - p[l].x * k;}
inline void print() {printf("seg %Lf %Lf\n",k,b);}
inline bool operator < (const Segment y) const{return nx * k + b < nx * y.k + y.b;}
};
set <Segment> S; set <Segment>::iterator it;
int main() {
n = read();
for(register int i = 1; i <= n + n; i += 2) {
p[i].rx = read(), p[i].ry = read(), p[i].get();
p[i + 1].rx = read(), p[i + 1].ry = read(), p[i + 1].get();
if(p[i + 1] < p[i]) swap(p[i], p[i + 1]); p[i].id = i, p[i + 1].id = i + 1;
q[i] = p[i], q[i + 1] = p[i + 1];
}
sort(q + 1, q + n + n + 1);
Segment tmp;
tmp.k = 0, tmp.b = -inf, tmp.lst = 0, S.insert(tmp);
for(register int i = 1, id; i <= n + n; ++i) {
nx = q[i].x, id = q[i].id;
if(id & 1) { // left
tmp.l = id, tmp.r = id + 1, tmp.lst = id, tmp.get();
it = S.insert(tmp).first; --it;
if(it->lst) p[it->lst].print(), p[id].print(), printf("\n");
it->lst = id;
}
else { // right
tmp.l = id - 1, tmp.r = id, tmp.lst = id, tmp.get();
it = S.find(tmp); --it;
it->lst = id, S.erase(tmp);
}
}
}

CEOI2020 道路(Roads) Solution的更多相关文章

  1. bzoj1621 / P2907 [USACO08OPEN]农场周围的道路Roads Around The Farm

    P2907 [USACO08OPEN]农场周围的道路Roads Around The Farm 基础dfs,按题意递归即可. #include<iostream> #include< ...

  2. [USACO08OPEN]农场周围的道路Roads Around The Farm BZOJ 1621 DFS

    Farmer John's cows have taken an interest in exploring the territory around the farm. Initially, all ...

  3. 洛谷 题解 P2296 【寻找道路】

    Problem P2296 [寻找道路] solution 首先声明,这题我用了spfa,而: 关于spfa:它死了. 杀手: NOI 2018−T1 出题人 感谢出题人,没有卡spfa 用时: 20 ...

  4. 【洛谷P2907】 【USACO08OPEN】农场周围的道路 水模拟分治

    P2907 [USACO08OPEN]农场周围的道路Roads Around The Farm 题目描述 Farmer John's cows have taken an interest in ex ...

  5. [APIO2008]

    A.免费道路roads 题意:给定n个点m条边的图,边有黑白颜色,求是否有一个生成树满足恰好有K条黑边,并输出方案. 题解:先加白边,求出必须加的黑边,然后加黑边到K条,剩下的用白边填充. 顺便说说, ...

  6. BZOJ1922:[SDOI2010]大陆争霸(最短路)

    Description 在一个遥远的世界里有两个国家:位于大陆西端的杰森国和位于大陆东端的 克里斯国.两个国家的人民分别信仰两个对立的神:杰森国信仰象征黑暗和毁灭 的神曾·布拉泽,而克里斯国信仰象征光 ...

  7. BZOJ 1626: [Usaco2007 Dec]Building Roads 修建道路( MST )

    计算距离时平方爆了int结果就WA了一次...... ------------------------------------------------------------------------- ...

  8. [Usaco2007 Dec]Building Roads 修建道路[最小生成树]

    Description Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农 ...

  9. P3008 [USACO11JAN]道路和飞机Roads and Planes

    P3008 [USACO11JAN]道路和飞机Roads and Planes Dijkstra+Tarjan 因为题目有特殊限制所以不用担心负权的问题 但是朴素的Dijkstra就算用堆优化,也显然 ...

随机推荐

  1. 汽车锂电池行业为啥会选择钡铼BL200系列Profinet分布式IO

    近年来,全球新能源汽车的蓬勃发展促进了锂电池行业的发展.随着锂电池标准化程度的提高,电池和模块规格的标准化是未来的发展趋势,也促进了自动化模块生产线的发展. 锂电池模块生产线通过涂胶-电池堆叠-组装- ...

  2. GreatSQL MGR FAQ

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 目录 0. GreatSQL简介 1. GreatSQL的特色有哪些 2. Gr ...

  3. 使用jmh框架进行benchmark测试

    性能问题 最近在跑flink社区1.15版本使用json_value函数时,发现其性能很差,通过jstack查看堆栈经常在执行以下堆栈 可以看到这里的逻辑是在等锁,查看jsonpath的LRUCach ...

  4. ASP.NET Core 6框架揭秘实例演示[32]:错误页面的集中呈现方式

    由于ASP.NET是一个同时处理多个请求的Web应用框架,所以在处理某个请求过程中出现异常并不会导致整个应用的中止.出于安全方面的考量,为了避免敏感信息外泄,客户端在默认情况下并不会得到详细的出错信息 ...

  5. 走进Redis:哨兵集群

    为什么需要哨兵 在 Redis 的主从库模式中,如果从库发生了故障,用户的操作是可以继续进行的,因为写操作是只在主库中进行的.那么,如果主库发生了故障,用户的操作将会收到影响.这时候可能会需要选择一个 ...

  6. 客户流失?来看看大厂如何基于spark+机器学习构建千万数据规模上的用户留存模型 ⛵

    作者:韩信子@ShowMeAI 大数据技术 ◉ 技能提升系列:https://www.showmeai.tech/tutorials/84 行业名企应用系列:https://www.showmeai. ...

  7. Canvas 线性图形(二):圆形

    函数 arc(x, y, radius, startAngle, endAngle, counterclockwise) 参数名 描述 x.y 圆心坐标轴 radius 圆的半径 startAngle ...

  8. 乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - 官方扩展集锦(Microsoft.Extensions on Nuget)

    什么是Microsoft.Extensions .NET Platform Extensions是一套.Net官方的API集合,提供了一些常用的编程模式和实用工具,例如依赖项注入.日志记录.缓存.Ho ...

  9. tqdm和zip组合使用时无法显示进度条-解决办法

    问题 单独对于可迭代对象iterator使用tqdm时,结合循环就可以在终端显示进度条, 以直观展示程序进度,如下: from tqdm import tqdm textlist = [] for i ...

  10. [BZOJ3625][CF438E]小朋友和二叉树 (多项式开根,求逆)

    题面 题解 设多项式的第a项为权值和为a的二叉树个数,多项式的第a项表示是否为真,即 则,所以F是三个多项式的卷积,其中包括自己: ,1是F的常数项,即. 我们发现这是一个一元二次方程,可以求出,因为 ...