题目链接:点我传送
(第一道不看题解过的题目==2333333
=====思考过程
先是想到最左边肯定是斜率最小的,最右边肯定是最大的(因为x趋近于-∞时斜率小的算出来大,因为x趋近于+∞时斜率大的算出来大。
于是就想到了把直线按照k从小到大排序。
后来又想到,k相等时,只有b最大的直线会出镜,别的不用管,所以排序时顺便去掉这些无用线。
于是就想到,三条直线Y1,Y2,Y3,满足K1<K2<K3,那么窝萌来考虑Y3遮住Y2的条件。
发现当且仅当Y3与Y2的交点比Y3和Y1的交点右边时,Y2会存在,否则会被Y3遮住。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <windows.h>
#define rep(j,k,l) for (int j=k;j<=l;j++)
using namespace std;
int pr[55555],haha[55555];
struct lych{
double x,y;
int num;
} line[55555];
bool cmp(const lych &xx,const lych &yy){
if (xx.x==yy.x) return xx.y>yy.y;
return xx.x<yy.x;
}
double cll(lych xx,lych yy){
return 1.0*(xx.y-yy.y)/(yy.x-xx.x);
}
double cl(int xx,int yy){
return cll(line[pr[xx]],line[yy]);
}
int n;
int main(){
//freopen("in.txt","r",stdin);
//freopen("1007.out","w",stdout);
scanf("%d",&n);
rep(i,1,n) scanf("%lf%lf",&line[i].x,&line[i].y),line[i].num=i;
sort(line+1,line+n+1,cmp);int ans=0;
//rep(i,1,n) printf("%.6f %.6f %d\n",line[i].x,line[i].y,line[i].num);
rep(i,1,n) if (i==1||line[i].x!=line[i-1].x){
//printf("%d\n",i);
if (ans<2){
ans++;
pr[ans]=i;
haha[ans]=line[i].num;
//printf("ok");
continue;
}
//printf("%.6f %.6f\n",cl(ans,i),cl(i,ans-1));
if (cl(ans,i)>cl(ans-1,i)){
//printf("%.6f %.6f\n",cl(ans,i),cl(i,ans-1));
ans++;
pr[ans]=i;
haha[ans]=line[i].num;
}
else{
pr[ans]=i;
haha[ans]=line[i].num;
}
//rep(i,1,ans) printf("%d ",haha[i]);
//printf("\n");
while (ans>=3&&cl(ans-1,i)<=cl(ans-2,i)){
ans--;
pr[ans]=pr[ans+1];
haha[ans]=haha[ans+1];
}
//rep(i,1,ans) printf("%d ",haha[i]);
//printf("\n");
}
sort(haha+1,haha+ans+1);
rep(i,1,ans) printf("%d ",haha[i]);
printf("\n");
system("pause");
return 0;
}