一开始看到这道题只能想到n^2暴力
不知道如何下手
实际上,我们要找到一种筛选的办法,这种筛选方法要在某种情况(顺序)下通用,
于是我们就可以按A值从大到小排序,用一个栈来维护后面加入的边
所以当一条边不合法,那它一定会被后来的边给弹出栈,具体可以通过求点的坐标来得知
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct mod{double A,B;int wei;};
mod q[50005];
bool cmp(mod x,mod y)
{
if (x.A>y.A)return true;
if (x.A<y.A)return false;
return x.B<y.B;
}
bool v[50005];
int t[50005],tp=0;
int main()
{
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&q[i].A,&q[i].B);
q[i].wei=i;
}
sort(q+1,q+n+1,cmp);
/*for (int i=1;i<=n;i++)
printf("i:%d %lf %lf\n",i,q[i].A,q[i].B);*/
tp++;
t[1]=1;
for (int i=2;i<=n;i++)
{
while(tp>1)
{
int o=t[tp];
double KK=q[i].A-q[o].A;
if (KK==0.0){tp--;continue;}
double BB=q[o].B-q[i].B;
double X2=BB/KK;
KK=q[i].A-q[t[tp-1]].A;
BB=q[t[tp-1]].B-q[i].B;
double X1=BB/KK;
if (X1<=X2)tp--;
else break;
}
tp++;
t[tp]=i;
}
memset(v,false,sizeof(v));
for (int i=1;i<=tp;i++)
v[q[t[i]].wei]=true;
bool tf=false;
for (int i=1;i<=n;i++)
if (v[i])
{
if (tf)printf(" ");
else tf=true;
printf("%d",i);
}
}