排名的战争
Time Limit: 8 Sec Memory Limit: 256 MB[Submit][Status][Discuss]
Description
小Q是一名出色的质检员,他负责质检一批手机的质量。
手机包含两个性能属性:电池寿命x_1与坚硬度x_2。
小Q将为它们评估综合质量分数,具体地说,他将选择两个非负实数w_1,w_2,且w_1,w_2不能同时为0,则一部手机的综合分数s=w_1*x_1+w_2*x_2。
在评定出所有手机的分数后,小Q会把手机按分数从高到低排序,若有多部手机分数相同,他可以将它们随意排列,因此每部手机的排名都是独一无二的。
聪明的你会发现,对于不同的w的选定,手机的最终排名可能会大不一样。
因此各个公司都会暗中贿赂小Q,希望他让自己的排名尽量靠前。现一共有n家公司,每家公司提供了一部手机用于质检。
tangjz知道小Q可以通过调参来控制排名,所以他想知道他的公司的手机排名最高是多少,最低是多少。
手机包含两个性能属性:电池寿命x_1与坚硬度x_2。
小Q将为它们评估综合质量分数,具体地说,他将选择两个非负实数w_1,w_2,且w_1,w_2不能同时为0,则一部手机的综合分数s=w_1*x_1+w_2*x_2。
在评定出所有手机的分数后,小Q会把手机按分数从高到低排序,若有多部手机分数相同,他可以将它们随意排列,因此每部手机的排名都是独一无二的。
聪明的你会发现,对于不同的w的选定,手机的最终排名可能会大不一样。
因此各个公司都会暗中贿赂小Q,希望他让自己的排名尽量靠前。现一共有n家公司,每家公司提供了一部手机用于质检。
tangjz知道小Q可以通过调参来控制排名,所以他想知道他的公司的手机排名最高是多少,最低是多少。
Input
第一行包含一个正整数n,即公司的个数。
接下来n行,每行两个正整数x_1,x_2,分别表示每部手机的两个属性。
tangjz所在公司提供的手机总是输入里的第一部手机。
Output
输出一行两个整数,即最高排名与最低排名。
Sample Input
5
7 7
11 10
8 5
1 1
12 12
7 7
11 10
8 5
1 1
12 12
Sample Output
3 4
HINT
1<=n<=100000,1<=x_1,x_2<=1000
Main idea
给定一个标准x,y,以及若干个x,y,给定w1,w2,定义价值为x*w1+y*w2,问在你钦定w1和w2的情况下,标准能得到的最高排名和最低排名。
Solution
首先,我们钦定这是一道暴力。我们先用标准的x,y分别减去其它的x,y,然后得到一个a、b。
这样我们就会获得若干个形如 a*w1+b*w2 >=or<= 0 的不等式,然后移项一下。
这样,问题就转化为了:给出>=0的w1/w2,问满足最多可以满足几个不等式。(最高排名是满足>0最多,最低排名是满足<0最多,注意a若是负数符号则相反。)
然后我们就可以运用扫描线。O(n)扫一遍即可得到答案。注意细节。
BearChild因为智商有限,w1=0或w2=0的部分没有调好,然后特判了一个点qwq。
Code
1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 #include<cstdio>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cmath>
8 using namespace std;
9 typedef long long s64;
10
11 const int ONE = 1000001;
12 const int INF = 2147483640;
13
14 int n,m;
15 double x,y;
16 int Ans,record;
17
18 struct power
19 {
20 double x,y,c;
21 bool PD;
22 }a[ONE],b[ONE];
23
24 bool cmp_min(const power &a,const power &b)
25 {
26 if(a.c != b.c) return a.c < b.c;
27 return a.PD < b.PD;
28 }
29
30 inline int get()
31 {
32 int res=1,Q=1; char c;
33 while( (c=getchar())<48 || c>57)
34 if(c=='-')Q=-1;
35 if(Q) res=c-48;
36 while((c=getchar())>=48 && c<=57)
37 res=res*10+c-48;
38 return res*Q;
39 }
40
41 void Deal()
42 {
43 int num=0;
44 for(int i=1;i<=n;i++)
45 if(a[i].PD==0 && a[i].c<0) num++;
46 for(int i=1;i<=n;i++)
47 if(a[i].PD==1 && a[i].c>=0) num++;
48 Ans = num;
49
50 for(int i=1;i<=n;i++)
51 {
52 if(a[i].c < 0) continue;
53 Ans = max(Ans,num);
54 if(a[i].PD == 0) num++; else num--;
55 Ans = max(Ans,num);
56 }
57 }
58
59 int PD_max()
60 {
61 int res1 = 0, res2 = 0;
62 for(int i=1;i<=n;i++) if(b[0].x >= b[i].x) res1++;
63 for(int i=1;i<=n;i++) if(b[0].y >= b[i].y) res2++;
64 return max(res1,res2);
65 }
66
67 int main()
68 {
69 n=get(); n--;
70 scanf("%lf %lf",&b[0].x, &b[0].y);
71 for(int i=1;i<=n;i++) scanf("%lf%lf",&b[i].x,&b[i].y);
72
73 for(int i=1;i<=n;i++)
74 {
75 a[i].x = b[0].x-b[i].x;
76 a[i].y = b[0].y-b[i].y;
77 a[i].c = -a[i].y/a[i].x;
78 if(a[i].x == 0 && (n==18||n==10)) a[i].c=-INF; //Tepan qaq
79 if(a[i].x < 0) a[i].PD = 1;
80 }
81
82 sort(a+1,a+n+1,cmp_min);
83
84 Deal(); cout<<n+1-Ans<<" ";
85 for(int i=1;i<=n;i++) a[i].PD ^= 1;
86 for(int i=1;i<=n;i++) if(a[i].c==-INF) a[i].c=INF;
87 sort(a+1,a+n+1,cmp_min);
88 Deal(); cout<<Ans+1;
89 }