Description
小Q是一名出色的質檢員,他負責質檢一批手機的質量。手機包含兩個性能屬性:電池壽命x_1與堅硬度x_2。小Q將
爲它們評估綜合質量分數,具體地說,他將選擇兩個非負實數w_1,w_2,且$_1,w_2不能同時爲0,則一部手機的綜
合分數s=w_1x_1+w_2x_2。在評定出所有手機的分數後,小Q會把手機按分數從高到低排序,若有多部手機分數相
同,他可以將它們隨意排列,因此每部手機的排名都是獨一無二的。聰明的你會發現,對於不同的w的選定,手機
的最終排名可能會大不一樣。因此各個公司都會暗中賄賂小Q,希望他讓自己的排名儘量靠前。現一共有n家公司,
每家公司提供了一部手機用於質檢。tangjz知道小Q可以通過調參來控制排名,所以他想知道他的公司的手機排名 最高是多少,最低是多少。
Input
第一行包含一個正整數n(1<=n<=100000),即公司的個數。
接下來n行,每行兩個正整數x_1,x_2(1<=x_1,x_2<=1000),分別表示每部手機的兩個屬性。
tangjz所在公司提供的手機總是輸入裏的第一部手機。
Output
輸出一行兩個整數,即最高排名與最低排名。
Sample Input
5
7 7
11 10
8 5
1 1
12 12
Sample Output
3 4
題解
根據平面向量的知識,我們可以把每個手機看作一個二維點
對於需要確定的兩個參數,可以看作
那一個手機的分數就相當於兩個向量相乘了
向量相乘還有另外一種定義,就是在某個向量上的投影乘這個向量的長度
顯然我們把所有向量投影到這個的向量上比較大小就可以知道排名了
回到本題
發現對於第一個手機,嚴格在左下方和嚴格在右上方的點都是無效的
要不就一直比他小要不就一直比他大
只用考慮在左上方和右下方的點
枚舉一個點,可以發現,使得1號點比這個點優秀的向量在斜率方面是一個連續的範圍
反之也是一個連續的範圍
對於左上方的點,把他和1號點作一條直線並取這條直線的垂線,不難只有向量在垂線的下方纔能使得1號點比這個點優秀,取補集即爲這個點比1號點優秀
右下方的點把上面的向量反過來就是同理的
於是處理出來這個就可以了…
最後可以差分一遍然後掃過去處理答案
注意要判掉斜率相等的情況,以及相同的情況
相同的時候顯然此時斜率爲正無窮
相同就不管了
我寫的這麼詳細不給個好評嗎…
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(LL x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
const int MAXN=100005;
struct line{double K;int c;}w[MAXN];int tot;
bool cmp(line n1,line n2){return n1.K>n2.K;}
int X[MAXN],Y[MAXN],n,base1,gg,base2;
int s[MAXN];
int main()
{
n=read();
for(int i=1;i<=n;i++)X[i]=read(),Y[i]=read();
for(int i=2;i<=n;i++)
{
if(X[i]==X[1]&&Y[i]==Y[1]){gg++;continue;}
if(X[i]>X[1]&&Y[i]>Y[1]){base1++;continue;}
if(X[i]<X[1]&&Y[i]<Y[1]){base2++;continue;}
if(Y[1]!=Y[i])
{
double K1=(double)(X[1]-X[i])/(Y[1]-Y[i]);
tot++;
w[tot].K=-1.0*K1;
if(X[i]<=X[1]&&Y[i]>=Y[1])w[tot].c=-1;
else w[tot].c=1;
}
else
{
tot++;w[tot].K=999999999;
if(X[i]<=X[1])w[tot].c=-1;
else w[tot].c=1;
}
}
//-1 在下面 1 在上面
sort(w+1,w+1+tot,cmp);
int lst=1;
for(int i=1;i<=tot;i++)
{
if(w[i].K!=w[i-1].K)lst=i;
if(w[i].c<0)
{
s[lst]++,s[tot+1]--;
}
else s[1]++,s[i+1]--;
}
int a1=0;
for(int i=1;i<=tot;i++)s[i]+=s[i-1],a1=max(a1,s[i]);
pr1(n-(a1+base2+gg));
memset(s,0,sizeof(s));
lst=1;
for(int i=1;i<=tot;i++)
{
if(w[i].K!=w[i-1].K)lst=i;
if(w[i].c>0)
{
s[lst]++,s[tot+1]--;
}
else s[1]++,s[i+1]--;
}
int a2=0;
for(int i=1;i<=tot;i++)s[i]+=s[i-1],a2=max(a2,s[i]);
pr2(a2+gg+base1+1);
return 0;
}