直接来构造。

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

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

找线段的过程用一个\(\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. 6.13 NOI 模拟

    \(T1\ first\) \(bitset\)字符串匹配 \(yyds\) \(O(\frac{n^2}{w})\)就是正解! #include<bits/stdc++.h> #defi ...

  2. [原创] RestartPC64-中文版v1.0.0.9

    原来发布的RestartPC-中文版和英文版v1.0.0.5,在PE64下无效.所以重新编译了64位版的RestartPC64-中文版v1.0.0.9,可以在PE64下面.正常Win64系统下面重启关 ...

  3. SVN:取消对代码的修改

    取消对代码的修改分为两种情况: 第一种情况:改动没有被提交(commit). 这种情况下,使用svnrevert就能取消之前的修改. svn revert用法如下: #svn revert[-R] s ...

  4. 《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(13)-Fiddler请求和响应断点调试

    1.简介 Fiddler有个强大的功能,可以修改发送到服务器的数据包,但是修改前需要拦截,即设置断点.设置断点后,开始拦截接下来所有网页,直到取消断点.这个功能可以在数据包发送之前,修改请求参数:在收 ...

  5. [网鼎杯 2018]Comment-1|SQL注入|二次注入

    1.打开之后只有一个留言页面,很自然的就想到了二次注入得问题,顺带查看了下源代码信息,并没有什么提示,显示界面如下: 2.那先扫描一下目录,同时随便留言一个测试以下,但是显示需要登录,账户.密码给出了 ...

  6. AI 音辨世界:艺术小白的我,靠这个AI模型,速识音乐流派选择音乐 ⛵

    作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 机器学习实战系列:https://www.showmeai.tech/t ...

  7. 在Laravel框架blog中,终端的一些命令

    创建控制器php artisan make:controller TestController数据库迁移php artisan make:migration create_goods_table实行迁 ...

  8. sedona(Geospark)读取csv

    package com.grady.sedona import org.apache.sedona.sql.utils.SedonaSQLRegistrator import org.apache.s ...

  9. Git Bash(提交文件到GitHub进行托管)

    ​ Introduction 使用Git Bash命令,可以将一个项目上传到Github官网中,进行托管,避免重要文件被误删 1.Git工具下载 Git for Windows 2.在github中新 ...

  10. Linux零拷贝原理

    Linux零拷贝原理 前言 磁盘可以说是计算机系统最慢的硬件之一,读写速度相差内存 10 倍以上,所以针对优化磁盘的技术非常的多,比如零拷贝.直接 I/O.异步 I/O 等等,这些优化的目的就是为了提 ...