题目描述
题解
由题意可知能看见的直线一定呈下凸。
以k为第一关键字,b为第二关键字排序,得到斜率不降、斜率相等时截距不降的直线序列。维护自底向上斜率单增的单调栈,当直线q[r-1]和当前枚举到的直线i共同将q[r]的最大值覆盖或者枚举到的i和q[r]平行时将q[r]弹出,最后在栈内的直线即为可以看到的直线。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
const int max_n=5e4+5;
int n,l,r,cnt,q[max_n],ans[max_n];
struct hp{int k,b,id;}a[max_n];
inline int cmp(hp a,hp b)
{
return a.k<b.k||(a.k==b.k&&a.b<b.b);
}
inline bool check(int x1,int x2,int x3)
{
LL w1=(LL)(a[x1].k-a[x3].k)*(LL)(a[x2].b-a[x1].b);
LL w2=(LL)(a[x1].k-a[x2].k)*(LL)(a[x3].b-a[x1].b);
return w1>=w2;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d%d",&a[i].k,&a[i].b),a[i].id=i;
sort(a+1,a+n+1,cmp);
l=r=0;
q[++r]=1;
for (int i=2;i<=n;++i)
{
while (l<r-1&&check(i,q[r-1],q[r])) r--;
while (l<r&&a[q[r]].k==a[i].k) r--;
q[++r]=i;
}
for (int i=l+1;i<=r;++i)
ans[++cnt]=a[q[i]].id;
sort(ans+1,ans+cnt+1);
for (int i=1;i<=cnt;++i)
printf("%d ",ans[i]);
}