[BZOJ1071][SCOI2007][堆]组队

[Problem Description]
NBA每年都有球员选秀环节。通常用速度和身高两项数据来衡量一个篮球运动员的基本素质。假如一支球队里速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height – minH ) + B * ( speed – minV ) <= C 其中A和B,C为给定的经验值。这个式子很容易理解,如果一个球队的球员速度和身高差距太大,会造成配合的不协调。 请问作为球队管理层的你,在N名选秀球员中,最多能有多少名符合条件的候选球员。
[Algorithm]
[Analysis]
好吧首先说这种方法是O(n ^ 2 log n)的,不过竟然可过……
首先预处理:Height = A * height, Weight = B * weight Val = Height + Weight
然后按照Weight 排序。枚举作为minHeight 的球员。再从大到小枚举作minWeight的队员。将能够组队的队员的Val放到堆里面去。每次minWeight更新的时候将堆里面不满足限制条件的弹出。由于每一轮枚举minHeight的时候,minWeight都是递减的而minHeight不变,所以已经从堆里面弹出的是不可能在入堆的……
[Code]
/**************************************************************
    Problem: 1071
    User: gaotianyu1350
    Language: C++
    Result: Accepted
    Time:1072 ms
    Memory:1392 kb
****************************************************************/
 
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
 
const long long MAXN = 5010;
 
priority_queue<int> q;
 
struct Node
{
    long long Height, Speed, Val;
    bool operator <(const Node a) const
    {
        return Val < a.Val;
    }
}a[MAXN];
 
bool cmp(const Node a, const Node b)
{
    return a.Speed > b.Speed;
}
 
long long A, B, C, n;
 
int main()
{
    scanf("%lld%lld%lld%lld", &n, &A, &B, &C);
    for (long long i = 1; i <= n; i++)
    {
        scanf("%lld%lld", &a[i].Height, &a[i].Speed);
        a[i].Height *= A;
        a[i].Speed *= B;
        a[i].Val = a[i].Height + a[i].Speed;
    }
    sort(a + 1, a + 1 + n, cmp);
    long long ans = 1;
    for (long long i = 1; i <= n; i++)
    {
        long long minHeight = a[i].Height;
        long long minSpeed = a[i].Speed;
        while (!q.empty()) q.pop();
        q.push(a[i].Val);
        for (long long j = 1; j <= n; j++)
            if (j != i && a[j].Height >= minHeight)
            {
                minSpeed = min(minSpeed, a[j].Speed);
                if (a[i].Val > C + minHeight + minSpeed) break;
                while (!q.empty() && q.top() > C + minHeight + minSpeed) q.pop();
                if (a[j].Val <= C + minHeight + minSpeed)
                {
                    q.push(a[j].Val);
                    ans = max(ans, (long long)q.size());
                }
            }
    }
    printf("%lld\n", ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值