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
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/chezhongyang/p/7763373.html