首页 > 其他 > 详细

luogu P3194 [HNOI2008]水平可见直线 |单调栈

时间:2020-05-26 22:03:20      阅读:46      评论:0      收藏:0      [点我收藏+]

题目描述

\(x-y\) 直角坐标平面上有 \(n\) 条直线 \(L_1,L_2,…L_n\)?,若在 \(y\) 值为正无穷大处往下看,能见到 \(L_i\) 的某个子线段,则称 \(L_i\)? 为可见的,否则 \(L_i\)? 为被覆盖的。 例如,对于直线: \(L_1:y=x\); \(L_2:y=-x\); \(L_3:y=0\); 则 \(L_1\)\(L_2\)? 是可见的,\(L_3\) 是被覆盖的。给出 \(n\) 条直线,表示成 \(y=Ax+B\) 的形式(\(|A|,|B| \le 500000\)),且 \(n\) 条直线两两不重合,求出所有可见的直线。

输入格式

第一行为 \(N\) (\(0<N<50000\)),接下来的 \(N\) 行输入 \(A_i,B_i\)?

输出格式

从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格。


#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e4+10;
#define int long long
#define db double
inline void read(int&x){
    x = 0;char c;int sign = 1;
    do{ c = getchar(); if(c == ‘-‘) sign = -1; }while(c < ‘0‘ || c>‘9‘);
    do{ x = x*10 + c -‘0‘;c = getchar(); }while(c <= ‘9‘ && c >= ‘0‘);
    x *= sign;
}
struct node{
	int A,B,id;	
}e[N];
const bool cmp(node t1,node t2){
	return (t1.A^t2.A) ? t1.A<t2.A : t1.B>t2.B ;
}
inline db sol(int i,int j){return (db)(e[i].B-e[j].B)/(db)(e[j].A-e[i].A);}
int n,st[N],ans[N],top;
signed main(){
	read(n);
	for(int i=1;i<=n;i++)read(e[i].A),read(e[i].B),e[i].id=i;
	sort(e+1,e+1+n,cmp);
	for(int i=1;i<=n;i++){
		if(e[i].A==e[i-1].A&&i!=1)continue;
		while(top>1&&sol(st[top],i)<=sol(st[top],st[top-1]))top--;
		st[++top]=i;
		ans[top]=e[i].id;
	}
	sort(ans+1,ans+1+top);
	for(int i=1;i<=top;i++)printf("%lld ",ans[i]);
}

luogu P3194 [HNOI2008]水平可见直线 |单调栈

原文:https://www.cnblogs.com/naruto-mzx/p/12968331.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!