[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 ...
随机推荐
- C++如何调用C#编写的 DLL
由于C#编绎出来的DLL不是计算机所能直接识别的二进制指令码,需要CLS进行再解释,说到这,我想有些朋友应该知道C#项目需要引用C++编写的DLL时,可以直接引用DLLMPORT来实现调用,而反向的话 ...
- 用canvas画一个的小画板(PC端移动端都能用)
前言 本篇的内容主要包括: canvas标签简介 画板的功能简介 画板的JS部分(包括:1.获取画布 2.使画板全屏幕显示且自适应 3.如何绘制直线 4.绘画时的三种状态(鼠标点击.移动.离开)5.画 ...
- 12:Challenge 5(线段树区间直接修改)
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 262144kB 描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)将某连续一段同时改成一个数 ...
- C语言-100加减求和
----------------------------度娘的思路------------------------------------------------------ Action() { / ...
- 第三方库requests
requests库 # 1.记得安装 第三方 模块 requests # pip install requests import requests url = 'http://www.baidu.co ...
- 【BZOJ4448】【SCOI2015】情报传递
这题面错别字真tm多 题意: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有若T名(可能没有)下线,除1名大头日外其余n-1 ...
- 【Paper Reading】Improved Textured Networks: Maximizing quality and diversity in Feed-Forward Stylization and Texture Synthesis
Improved Textured Networks: Maximizing quality and diversity in Feed-Forward Stylization and Texture ...
- linux 调试相关命令
1. tail -f filename 调试时,log输出到文件,但是又想看到即时输出信息 未完待续....
- sz xshell
yum install lrzsz -y
- swoole之memoryGlobal内存池分析
内存池的作用: 直接使用系统调用malloc会有如下弊端: 频繁分配内存时会产生大量内存碎片 频繁分配内存增加系统调用开销 容易造成内存泄漏 内存池是预先申请一定数量的,大小相等的内存块作为预备使用: ...