4880: [Lydsy2017年5月月赛]排名的战争
Time Limit: 8 Sec Memory Limit: 256 MB
Submit: 265 Solved: 47
[Submit][Status][Discuss]
Description
小Q是一名出色的质检员,他负责质检一批手机的质量。手机包含两个性能属性:电池寿命x_1与坚硬度x_2。小Q将
为它们评估综合质量分数,具体地说,他将选择两个非负实数w_1,w_2,且$_1,w_2不能同时为0,则一部手机的综
合分数s=w_1*x_1+w_2*x_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
HINT
Source
鸣谢Claris上传试题
[Submit][Status][Discuss]
把问题转换一下
变成需要求最多有多少人分数更低,最少有多少人分数更低
把每个公司的手机的两个参数看成点 (x,y)
分数更优的条件就等价于 w1x1+w2y1≥w1x2+w2y2
移项得到 −w1w2≥y2−y1x2−x1 或 −w1w2≤y2−y1x2−x1
能满足一组 w1,w2 的点恰好在同一个半平面
于是以一号手机为原点,其它点按照极角序排好,扫一遍就行了
边界上的点要特别提出来,因为评分相同的手机需要加上排名特技
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef double DB;
typedef pair <DB,int> pr;
const int maxn = 2E5 + 20;
const DB _180 = acos(-1.00);
const DB _90 = _180 / 2.00;
const DB _360 = _180 * 2.00;
const DB EPS = 1E-10;
int n,X,Y,Max,Min = ~0U>>1,tot,c1,c2,cur = 1,sum[maxn];
DB ang[maxn],A[maxn];
pr p[maxn];
#define fr first
#define sc second
#define mp(a,b) (make_pair((a),(b)))
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
inline int fcmp(DB x)
{
return fabs(x - _180) <= EPS ? 0 : (x < _180 ? -1 : 1);
}
inline int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); X = getint(); Y = getint();
for (int i = 1; i < n; i++)
{
int x = getint(),y = getint();
if (x > X && y > Y) continue;
if (x < X && y < Y) {++c2; continue;}
if (x == X && y == Y) {++c1; continue;}
p[++tot] = mp(atan2(y - Y,x - X),1);
if (p[tot].fr < 0 || fabs(p[tot].fr) <= EPS) p[tot].fr += _360;
if (x >= X && y <= Y) p[++tot] = mp(atan2(y - Y,x - X) + _180,0);
}
sort(p + 1,p + tot + 1);
for (int i = 2; i <= tot; i++)
if (fabs(p[i].fr - p[i - 1].fr) <= EPS) p[cur].sc += p[i].sc;
else p[++cur] = p[i];
for (int i = 1; i <= cur; i++) sum[i] = p[i].sc + sum[i - 1];
int pos = 1;
for (int i = 1; i <= cur; i++)
{
if (fcmp(p[i].fr) == 1) break;
while (pos < cur && fcmp(p[pos + 1].fr - p[i].fr) <= 0) ++pos;
Max = max(Max,sum[pos] - sum[i - 1]);
int now = sum[pos] - sum[i];
if (fcmp(p[pos].fr - p[i].fr) == 0) now -= p[pos].sc;
Min = min(Min,now);
}
printf("%d %d\n",n - Max - c1 - c2,n - Min - c2);
return 0;
}