BZOJ 3354 Hiring

BZOJ 3354

考虑枚举Level=1给多少钱
那就是有些人不会来
来的人贪心得从Level最小的开始选
这个贪心正确性显然

哪怎么枚举呢
每个人可以算出给1Level多少钱他才来
对这个值排序,从小到大扫,维护选的人的集合

怎么维护?
对于一个新人能要就要(钱足够)
不能要(钱不够)就看看是不是踢掉已选的Level最大的人
连续踢直至MaxLevel<NewLevel或钱够了

我怎么交了一个I64d还能A?

#include <cstdio>
#include <queue>
#include <algorithm>

using std::sort;
using std::max;
using std::priority_queue;

const int MAXN=500111;

int N;
long long W;
int Ans;

struct Peo{
    long long Lim, Lev;
} P[MAXN];

bool operator < (Peo A, Peo B){
    return A.Lim*B.Lev<B.Lim*A.Lev;
}

long long LevSum;
int Cnt;

priority_queue<long long> PQ;

int main(){
    
    scanf("%d%I64d", &N, &W);
    for(int i=1;i<=N;++i)
        scanf("%I64d%I64d", &P[i].Lim, &P[i].Lev);
    
    sort(P+1, P+N+1);
    
    for(int i=1;i<=N;++i){
        while(!PQ.empty() && PQ.top()>P[i].Lev && (LevSum+P[i].Lev)*P[i].Lim>W*P[i].Lev){
            --Cnt;
            LevSum-=PQ.top();
            PQ.pop();
        }
        if((LevSum+P[i].Lev)*P[i].Lim<=W*P[i].Lev){
            ++Cnt;
            LevSum+=P[i].Lev;
            PQ.push(P[i].Lev);
            Ans=max(Ans, Cnt);
        }
    }
    
    printf("%d\n", Ans);
    
    return 0;
}

/*
4 100
5 1000
10 100
8 10
20 1

2

*/

转载于:https://www.cnblogs.com/Pickupwin/p/9617866.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值