BZOJ 1071: [SCOI2007]组队
1071: [SCOI2007]组队
Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 2420 Solved: 769
[Submit][Status][Discuss]
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在长整型以内。
2016.3.26 数据加强 Nano_ape 程序未重测
题解
当确定minh和minv时,球员要满足A*h+B*v<=A*minh+B*minv+C才可以加入,所以用数组存下A*h+B*v的值,从小到大排序,再将原数组按h排序,枚举minv。
要满足h>=minh,所以v的取值范围是minv到minv+C/B。
从小到大枚举minh,所以A*minh+B*minv+C是递增的,满足A*h+B*v<=A*minh+B*minv+C的范围也是递增的,即满足上一个minh的点一定满足当前minh,所以利用单调性,每次minh增大,就将新的满足的点加进去,因为上次加的点中满足条件但h小于当前minh的点不再满足,又因为h也是递增的,所以也是利用单调性,将这些点删掉。
代码
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #define LL long long using namespace std; const int N=5005; int n,ans; LL A,B,C; struct member{ int h,v; LL sum; }a[N],b[N]; bool cmp1(member a,member b){ return a.h<b.h; } bool cmp2(member a,member b){ return a.sum<b.sum; } int main(){ scanf("%d%lld%lld%lld",&n,&A,&B,&C); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].h,&a[i].v); b[i]=a[i]; b[i].sum=A*b[i].h+B*b[i].v; } sort(a+1,a+n+1,cmp1); sort(b+1,b+n+1,cmp2); LL mn,mx; int p1,p2,cnt; for(int i=1;i<=n;i++){ mn=a[i].v,mx=a[i].v+C/B; p1=p2=cnt=0; for(int j=1;j<=n;j++){ while(p1<n&&b[p1+1].sum<=A*a[j].h+B*a[i].v+C){ p1++; if(b[p1].v>=mn&&b[p1].v<=mx)cnt++; } while(p2<n&&a[p2+1].h<a[j].h){ p2++; if(a[p2].v>=mn&&a[p2].v<=mx)cnt--; } ans=max(ans,cnt); } } printf("%d\n",ans); return 0; }