直接来构造。

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

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

找线段的过程用一个\(\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. 网站加了CDN后,字体图标报错Access-Control-Allow-Origin

    这两天将自己做的网站(PM老猫)上线了,上线后发现因为之前购买的服务器带宽较小,第一次打开网站页面就会比较慢,想着给网站加了个CDN,让静态文件直接通过CDN访问.网上一找发现可以白嫖的CDN服务挺多 ...

  2. 使用JDK的同步容器时,应该避免那些坑?

    摘要:在使用JDK中的同步容器时,应该尽量避免哪些坑 本文分享自华为云社区<[高并发]亿级流量高并发秒杀系统商品"超卖"了,只因使用的JDK同步容器中存在这两个巨大的坑!!( ...

  3. Nodemon 如何实时监听 TypeScript 项目下的文件并热部署?

    首先你的项目要安装ts-node和nodemon: npm i -D ts-node nodemon 在package.json文件中配置运行脚本: "dev": "no ...

  4. ceph 010 clustermap ceph调优

    cluster map [ceph: root@clienta /]# ceph mon dump epoch 4 fsid 2ae6d05a-229a-11ec-925e-52540000fa0c ...

  5. 操作系统学习笔记5 | 用户级线程 && 内核级线程

    在上一部分中,我们了解到操作系统实现多进程图像需要组织.切换.考虑进程之间的影响,组织就是用PCB的队列实现,用到了一些简单的数据结构知识.而本部分重点就是进程之间的切换. 参考资料: 课程:哈工大操 ...

  6. 「雅礼集训 2017 Day2」水箱 (数据结构+dp ,一个log)

    题面 题解 在网上看到有些做法,有什么平衡树.启发式合并等等总之复杂度O(Tnlog^2(n))的不优做法,这里我就用一个O(Tnlogn)的做法好了 其实大体上推导的思路都是一样的. 我们很容易发现 ...

  7. JZOJ3542冒泡排序

    题面 下面是一段实现冒泡排序算法的C++代码: for (int i=1;i<=n-1;i++)  for (int j=1;j<=n-i ;j++)  if(a[j]>a[j+1] ...

  8. 使用Python批量爬取美女图片

    运行截图 实列代码: from bs4 import BeautifulSoup import requests,re,os headers = { 'User-Agent': 'Mozilla/5. ...

  9. 【JAVA】学习路径35-InputStream使用例子

    import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; pu ...

  10. flex常用布局

    公共样式: <style> * { margin: 0; padding: 0; } .has-flex { display: flex; } </style> 垂直居中 子元 ...