单调栈存放直线,把直线按斜率升序排序枚举 l i l_i li与栈顶直线的交点如果在栈顶与次栈顶的交点左边,那么栈顶代表的直线是不可视的,弹出。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const int N = 50050;
int sgn(double x){
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
return -1;
}
struct Point{
double x, y;
Point(double x = 0, double y = 0):x(x), y(y){
}
}last;
struct Line{
double a, b;
int id;
Line(double a = 0, double b = 0):a(a), b(b){
}
void input(int x){
id = x;
scanf("%lf%lf", &a, &b);
}
Point operator^ (const Line& p) const{
if(a == p.a) return Point(inf, inf);
double t = (p.b-b)/(a-p.a);
return Point(t, a*t+b);
}
}l[N], st[N];
bool cmp(Line& l1, Line& l2){
if(sgn(l1.a-l2.a)) return sgn(l1.a-l2.a)<0;
return sgn(l1.b-l2.b)>0;
}
bool cmp1(Line& l1, Line& l2){
return l1.id < l2.id;
}
int tot;
int main(){
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) l[i].input(i);
sort(l+1, l+n+1, cmp);
for(int i = 1; i <= n; i++){
if(tot == 0) {
st[++tot] = l[i];
last = Point(-inf, -inf);
continue;
}
if(sgn(st[tot].a-l[i].a) == 0) continue;
Point ne = st[tot]^l[i];
while(sgn(ne.x-last.x) <= 0 && tot > 1){
--tot;
last = st[tot]^st[tot-1];
ne = st[tot]^l[i];
}
last = l[i]^st[tot];
st[++tot] = l[i];
}
sort(st+1, st+tot+1, cmp1);
for(int i = 1; i <= tot; i++) printf("%d ", st[i].id);
return 0;
}