題目鏈接:點我傳送
(第一道不看題解過的題目==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;
}