[HNOI2008]水平可见直线 单调栈
题目描述:
在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
可见的,否则Li为被覆盖的.
例如,对于直线:
L1:y=x; L2:y=-x; L3:y=0
则L1和L2是可见的,L3是被覆盖的.
给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.
题解:
一道很好的思维题。
1.简单手画一下,能被看到的直线应该是所有直线一起围成的大凸包。
2.由于是凸包,我们考虑将所有直线按斜率排序,从小到大依次加入到平面直角坐标系中。
3.我们考虑一下新加入直线的情况:

在这种情况中,我们可以看到新加入的红色直线与加入之前平面中斜率第二大的直线的交点位于先前第一大与第二大之左,显然,这就会挡住平面中斜率第二大的直线,我们就将该直线弹出,直到找到一个交点在新加入直线的交点左侧。
对于整个过程,直线的斜率单调递增,交点横坐标也单调递增,直接用单调栈维护即可。
时间复杂度为 $O(n)$
Code:
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
void setIO(string a){
freopen((a+".in").c_str(),"r",stdin);
}
const int maxn=100000+5;
struct Line{
double slope, y;
}line[maxn];
int arr[maxn],ans[maxn],S[maxn],top;
bool cmp(int i,int j){
if(line[i].slope==line[j].slope) return line[i].y>line[j].y;
return line[i].slope<line[j].slope;
}
double get(int i,int j){
return (line[i].y-line[j].y)/(line[j].slope-line[i].slope);
}
int main(){
//setIO("input");
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%lf%lf",&line[i].slope,&line[i].y);
arr[i]=i;
}
sort(arr+1,arr+1+n,cmp);
for(int i=1;i<=n;++i)
{
int cur=arr[i]; if(line[cur].slope==line[arr[i-1]].slope && i!=1) continue;
while(top>1 && get(S[top],S[top-1])>=get(arr[i],S[top])) --top;
S[++top]=cur;
ans[top]=cur;
}
sort(ans+1,ans+1+top);
for(int i=1;i<=top;++i) printf("%d ",ans[i]);
return 0;
}
[HNOI2008]水平可见直线 单调栈的更多相关文章
- BZOJ1007: [HNOI2008]水平可见直线(单调栈)
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 8638 Solved: 3327[Submit][Status][Discuss] Descripti ...
- bzoj1007: [HNOI2008]水平可见直线 单调栈维护凸壳
在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.例如,对于直线:L1:y=x; L2:y=-x; L3 ...
- bzoj1007 [HNOI2008]水平可见直线——单调栈
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1007 可以把直线按斜率从小到大排序,用单调栈维护,判断新直线与栈顶的交点和栈顶与它之前直线的 ...
- bzoj1007/luogu3194 水平可见直线 (单调栈)
先按斜率从小到大排序,然后如果排在后面的点B和前面的点A的交点是P,那B会把A在P的右半段覆盖掉,A会把B在P的左半段覆盖掉. 然后如果我们现在又进来了一条线,它跟上一条的交点还在上一条和上上条的左边 ...
- bzoj 1007 [HNOI2008]水平可见直线(单调栈)
1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5120 Solved: 1899[Submit][Sta ...
- BZOJ 1007 [HNOI2008]水平可见直线 (栈)
1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7940 Solved: 3030[Submit][Sta ...
- BZOJ 1007: [HNOI2008]水平可见直线 栈/计算几何
1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MB 题目连接 http://www.lydsy.com/JudgeOnline ...
- 【BZOJ1007】[HNOI2008]水平可见直线 半平面交
[BZOJ1007][HNOI2008]水平可见直线 Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见 ...
- 【bzoj1007】[HNOI2008]水平可见直线
1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5932 Solved: 2254[Submit][Sta ...
随机推荐
- Xshell dns tunnel攻击
该域名还会向多个超长域名做渗出,且域名采用了 DGA 生成算法,通过 DNS 解析时渗出数据. 部分生成域名如下: sajajlyoogrmkjlkmosbxowcrmwlvajdkbtbjoylyp ...
- hexo博客谷歌百度收录踩坑日记
title: hexo博客谷歌百度收录踩坑日记 toc: false date: 2018-04-17 00:09:38 百度收录文件验证 无论怎么把渲染关掉或者render_skip都说我的格式错误 ...
- POJ 2190 模拟
按照题意模拟就好- 注意"X"只能出现在最后一位... // by SiriusRen #include <cstdio> using namespace std; c ...
- html5+css3+javascript 自定义提示窗口
效果图: 源码: 1.demo.jsp <%@ page contentType="text/html;charset=UTF-8" language="java& ...
- APICloud关闭Key Building Resolve
顶部菜单 --> 扩展 --> keybinding resolver --> toggle
- ZBrush实用插件ZAppLink简介
ZAppLink是ZBrush版本推出时被评为最值得期待的插件.事实证明,ZAppLink的出现让工具与工具之间有了交流,搭起软件与软件的沟通桥梁. ZAppLink插件专用于扩展ZBrush®的绘制 ...
- vue路由跳转传参
this.$router.push({ path: '/message/result_notice', query: { id: id } }) // let type = this.$route.n ...
- [Java] 使用 Apache的 Commons-net库 实现FTP操作
因为最近工作中需要用到FTP操作,而手上又没有现成的FTP代码.就去网上找了一下,发现大家都使用Apache的 Commons-net库中的FTPClient. 但是,感觉用起来不太方便.又在网上找到 ...
- 题解 洛谷 P4047 【[JSOI2010]部落划分】
我觉得几乎就是一道最小生成树模板啊... 题解里许多大佬都说选第n-k+1条边,可我觉得要这么讲比较容易理解 (虚边为能选的边,实边为最小生成树) 令n=5,k=2,(1,3)<(1,2)< ...
- [转载]深入Java单例模式
在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就单例设计模式详细的探讨一下. 所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在 ...