1071: [SCOI2007]组队 - BZOJ
Description
NBA每年都有球员选秀环节。通常用速度和身高两项数据来衡量一个篮球运动员的基本素质。假如一支球队里速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height – minH ) + B * ( speed – minV ) <= C 其中A和B,C为给定的经验值。这个式子很容易理解,如果一个球队的球员速度和身高差距太大,会造成配合的不协调。 请问作为球队管理层的你,在N名选秀球员中,最多能有多少名符合条件的候选球员。
Input
第一行四个数N、A、B、C 下接N行每行两个数描述一个球员的height和speed
Output
最多候选球员数目。
Sample Input
4 1 2 10
5 1
3 2
2 3
2 1
Sample Output
4
HINT
数据范围: N <= 5000 ,height和speed不大于10000。A、B、C在长整型以内。
做了这道题,我深深的体会到了longint和int64时间上的差异(因为最开始用的是int64,怕乘起来会爆longint)
现在开始分析题目
把那个式子变一下,就变成了a*x+b*y<=c+a*minx+b*miny(注意x>=minx,y>=miny)
我们暴力的想法是O(n^3)先枚举minx和miny,再枚举可行的点
因为a*x+b*y是定值,所以我们先排序,在枚举枚举minx时把比minx小的点删掉,枚举miny的时候把比miny小的点删掉(注意不要重复删除)
然后可以用树状数组维护和的信息,这样是O(n^2*logn)的
但是我们可以做得更好,我们从小到大枚举minx和miny,minx确定后c+a*minx+b*miny是递增的,所以只要拿一个指针往后移加到sum里去就行了(确定minx后把信息全部赋为初值)
这样就是O(n^2)的,用pascal的同学千万别用int64,用longint快一些,int64TLE无数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const 2 maxn=5010; 3 type 4 aa=array[0..maxn]of longint; 5 var 6 n,num,a,b,c:longint; 7 x,y,z,k,yi,zi:aa; 8 9 procedure swap(var x,y:longint); 10 var 11 t:longint; 12 begin 13 t:=x;x:=y;y:=t; 14 end; 15 16 procedure sort(l,r:longint;var a,b:aa); 17 var 18 i,j,y:longint; 19 begin 20 i:=l; 21 j:=r; 22 y:=a[(l+r)>>1]; 23 repeat 24 while a[i]<y do 25 inc(i); 26 while a[j]>y do 27 dec(j); 28 if i<=j then 29 begin 30 swap(a[i],a[j]); 31 swap(b[i],b[j]); 32 inc(i); 33 dec(j); 34 end; 35 until i>j; 36 if i<r then sort(i,r,a,b); 37 if j>l then sort(l,j,a,b); 38 end; 39 40 procedure init; 41 var 42 i:longint; 43 begin 44 read(n,a,b,c); 45 for i:=1 to n do 46 read(x[i],y[i]); 47 sort(1,n,x,y); 48 for i:=1 to n do 49 begin 50 k[i]:=y[i]; 51 yi[i]:=i; 52 end; 53 sort(1,n,k,yi); 54 for i:=1 to n do 55 begin 56 k[i]:=i; 57 zi[i]:=a*x[i]+b*y[i]; 58 end; 59 sort(1,n,zi,k); 60 for i:=1 to n do 61 if (zi[i]=zi[i-1]) and (i<>1) then z[k[i]]:=z[k[i-1]] 62 else z[k[i]]:=z[k[i-1]]+1; 63 num:=0; 64 for i:=1 to n do 65 if zi[i]<>zi[i-1] then 66 begin 67 inc(num); 68 zi[num]:=zi[i]; 69 end; 70 end; 71 72 var 73 vis:array[0..maxn]of boolean; 74 75 procedure work; 76 var 77 ans,sum,i,j,l,p:longint; 78 begin 79 ans:=0; 80 for i:=1 to n do 81 begin 82 if (i=1) or (x[i]<>x[i-1]) then 83 begin 84 sum:=0; 85 l:=0; 86 for j:=1 to num do 87 k[j]:=0; 88 for j:=i to n do 89 inc(k[z[j]]); 90 for j:=1 to n do 91 if vis[yi[j]]=false then 92 begin 93 p:=c+a*x[i]+b*y[yi[j]]; 94 while (zi[l+1]<=p)and(l<num) do 95 begin 96 inc(l); 97 inc(sum,k[l]); 98 end; 99 if ans<sum then ans:=sum; 100 if zi[l]>=a*x[yi[j]]+b*y[yi[j]] then dec(sum); 101 dec(k[z[yi[j]]]); 102 end; 103 end; 104 vis[i]:=true; 105 if i+ans>n then break; 106 end; 107 write(ans); 108 end; 109 110 begin 111 init; 112 work; 113 end.