BZOJ4614/UVA1742 Oil 计算几何
传送门
题意:在平面直角坐标系中给出$N$条互不相交的、与$x$轴平行、且在$x$轴上方的线段,每一条线段的价值为其长度。求一条不与$x$轴平行的直线,使得与这条直线相交的线段的价值之和最大,求出这个和。$N \leq 2000 , -10^6 \leq \text{线段两端点横坐标} \leq 10^6 , 1 \leq \text{线段两端点纵坐标} \leq 10^6$
首先我们可以想到:必定存在一条最优的直线,它经过某一条线段的左端点和某条线段的右端点,因为如果某条最优的直线不满足这些性质,我们可以通过旋转和平移使其满足条件。基于上面的结论,我们可以很轻松地想到一种算法:枚举直线经过哪一条线段的左端点和哪一条线段的右端点,然后扫一遍所有的线段看其是否被该直线穿过。这样子的复杂度是$O(n^3)$的。
接着我们考虑优化。我们这样考虑:枚举直线经过其左端点的线段,那么某一条线段会产生贡献当且仅当直线的斜率在某一个区间之内。那么我们将所有线段的会产生贡献的区间算出来,问题就转化为了:给定若干区间,每个区间有权值,选择一个点使得包含这个点的区间的权值之和最大。这个问题可以利用尺取法:按照左端点从小到大加入区间,删除与新加入的区间不相交的区间,计算剩余的权值和。这种算法的复杂度就降为了$O(n^2logn)$
一个细节:为了避免区间不连续、斜率不存在的情况,我们可以计算每一个线段产生贡献时,直线斜率的倒数会落在哪一段区间$($我们认为直线的斜率不存在的时候,斜率的倒数为$0)$,这样每一个线段的贡献区间就是连续的,还可以在计算斜率时避免除$0$。
//一份常数极大的Code #include<bits/stdc++.h> #define ld long double #define eps 1e-12 using namespace std; inline int read(){ ; ; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = ; c = getchar(); } while(isdigit(c)){ a = (a << ) + (a << ) + (c ^ '); c = getchar(); } return f ? -a : a; } struct range{ ld l , r; int ind; }now[] , ano[]; ][]; inline long long max(long long a , long long b){ return a > b ? a : b; } inline void swap(int &a , int &b){ int t = a; a = b; b = t; } inline void swap(ld &a , ld &b){ ld t = a; a = b; b = t; } bool cmp1(range l , range r){ return l.l < r.l; } bool cmp2(range l , range r){ return l.r < r.r; } inline ld calcK(int x1 , int y1 , int x2 , int y2){ return (ld)(x1 - x2) / (y1 - y2); } int main(){ int N; while(scanf("%d" , &N) != EOF){ ; i <= N ; i++){ num[i][] = read(); num[i][] = read(); num[i][] = read(); ] < num[i][]) swap(num[i][] , num[i][]); } ; ; i <= N ; i++){ ; ; j <= N ; j++) ] != num[j][]){ now[++cnt].l = calcK(num[i][] , num[i][] , num[j][] , num[j][]); now[cnt].r = calcK(num[i][] , num[i][] , num[j][] , num[j][]); now[cnt].ind = j; if(now[cnt].l > now[cnt].r) swap(now[cnt].l , now[cnt].r); now[cnt].l -= eps; now[cnt].r += eps; ano[cnt] = now[cnt]; } sort(now + , now + cnt + , cmp1); sort(ano + , ano + cnt + , cmp2); ; ] - num[i][]; maxN = max(maxN , ans); ; j <= cnt ; j++){ ans += num[now[j].ind][] - num[now[j].ind][]; while(ano[p].r < now[j].l){ ans -= num[ano[p].ind][] - num[ano[p].ind][]; ++p; } maxN = max(maxN , ans); } } printf("%lld\n" , maxN); } ; }
BZOJ4614/UVA1742 Oil 计算几何的更多相关文章
- BZOJ4614 UVA1742 Oil 计算几何+搜索+扫描线
正解:计算几何+搜索+扫描线 解题报告: 传送门 哇我是真的觉得这题很妙了!各个方面都很妙啊... 首先有一个很重要的结论:最优线一定可以通过各种变换(旋转/平移)使得经过一条线段的左端点(...并不 ...
- BZOJ4614 [Wf2016]Oil
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- HDU5033 building 单调栈+计算几何
正解:单调栈 解题报告: 哇生气辽QAQ本来打了半天feel good都快调出来了然后说换题了QAQ(所以可能那题的代码会过一阵子再放上来了QAQ 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
- BZOJ 4614 【Wf2016】 Oil
题目链接:Oil 感觉同时几线作战有点吃不消啊-- 这道题有一个显然的结论,那就是最优的直线一定过某条线段的端点. 仔细想想很有道理.如果最终的直线没有过线段的端点的话,那么这条直线就一定可以平移,直 ...
- ACM/ICPC 之 计算几何入门-叉积-to left test(POJ2318-POJ2398)
POJ2318 本题需要运用to left test不断判断点处于哪个分区,并统计分区的点个数(保证点不在边界和界外),用来做叉积入门题很合适 //计算几何-叉积入门题 //Time:157Ms Me ...
- HDU 2202 计算几何
最大三角形 Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- ACM 计算几何中的精度问题(转)
http://www.cnblogs.com/acsmile/archive/2011/05/09/2040918.html 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模 ...
- Oil Deposits
Oil Deposits Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- hdu 2393:Higher Math(计算几何,水题)
Higher Math Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- AWT初步— 事件处理模型
之前学习的内容只能形成一个用户界面,而用户不能对其有实际的操作,也就是说用户界面没有任何功能.要能够让图形界面接收用户的操作,就必须给各个组件加上事件处理机制.在事件处理的过程中,主要涉及三类对象: ...
- html基本标签(慕课网)
html标签: 1.<q>标签,短文本引用(quote,引用) 注解:引用短文本,比如引用古人的一句话 ,注意引用的文本不需要再加双引号. <q>标签的真正关键点不是它的默认样 ...
- C#与Java AES 加密解密
参考文档:https://www.cnblogs.com/xbzhu/p/7064642.html 前几天对接Java接口,需要C#加密参数,Java解密.奈何网上找了一堆大同小异的加解密方法都跟Ja ...
- Asp.net MVC通过自定义特性实现Action日志记录
一.自定义特性 /// <summary> /// 描述特性 /// </summary> [AttributeUsage(AttributeTargets.Method)] ...
- Django知识补充
目录 一.文件上传 二.Models补充 三.Django总结 一.文件上传 1.通过form表单或者通过From类上传 views.py from django.shortcuts import r ...
- tidb在DDL语句方面的测试
Mysql与tidb测试数据为8000万行. 1.修改一个字段的列名,比如将“ctime”修改为“cctime”. Tidb测试: MySQL测试: 2.同一属性之间切换,即修改一个字段的属性大小.比 ...
- 5.1Python函数(一)
目录 目录 前言 (一)函数的基本知识 (二)函数的基本使用 ==1.函数的简单定义== ==2.传值函数== (3)输出效果 ==3.不定长函数== ==4.缺省函数== ==5.函数的传值过程== ...
- elasticsearch使用bulk实现批量操作
本篇文章提供ES原生批量操作语法及使用bulk批量操作文档.文章依旧提供语法,具体实现大家根据语法,在对应处进行替换即可 一.原生批量获取文档 1.获取指定文档值(1) 语法: GET /_mget ...
- map的使用注意事项
map是无序的,每次打印出来的map都会不一样,它不能通过index获取,而必须通过key获取 map的长度是不固定的,也就是和slice一样,也是一种引用类型 内置的len函数同样适用于map,返回 ...
- java用星星符号打印出一个直角三角形
package debug; public class Demo10 { public static void main(String[] args) { //用星星符号打印出一个直角三角形 for( ...