题解 | #Cow Acrobats#

Cow Acrobats

https://ac.nowcoder.com/acm/problem/50958

一、思路

本题使用二分搜素,可以使用一个简单的思路解决,二分的mid为牛组成的序列的最大的危险值。

解题目的核心是二分的judge算法,我们能够知道,最底下的一头牛,所承担的危险值为,所有牛承担的危险值减去它的质量再减去它的力量。同时二分传递的mid为序列中最大的风险值,那么对于最底下的那头牛,可以推出如下的表达式

所有牛的质量-最底下的牛的质量-最底下的牛的力量=最底下的牛的风险值<=mid

所有牛的质量-最底下的牛的质量-最底下的牛的力量<=mid

所有牛的质量-mid<=最底下的牛的质量+最底下的牛的力量

那么我们先根据(牛的质量+牛的力量)进行升序排序,用lowerBound找到满足条件的牛,这些就是可以放在最底下的牛,然后对于下一头牛,需要满足的规则为

所有牛的质量-以选择的牛的质量和-该的牛的质量-该的牛的力量=该牛的风险值<=mid

所有牛的质量-以选择的牛的质量和-该的牛的质量-该的牛的力量<=mid

所有牛的质量-以选择的牛的质量和-mid<=该的牛的质量+该的牛的力量

那么不难看出,我们要尽最大可能维护这个表达式可行时,一定要先选择那些质量大的牛,所以我们每一次用lower_bound找到满足条件的所有牛之后,都通过优先队列,选择质量最大的牛,然后记录count++用总质量减去已选择的质量再次进行判断。(这里注意优先队列的值不要放重复了)

最后count==N,那么就代表mid可行,同时我们需要把数字第N+1个位置放置无穷大,如果找到了第N+1个位置,或者满足条件的牛都用过了(优先队列为空),那么就证明mid过小。

二、代码

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
struct Cow
{
    ll weight, strength;
    Cow(ll weight = 0, ll strength = 0) : weight(weight), strength(strength) {}
};
Cow cows[50007];
int N;
ll inf = 0x3f3f3f3f3f3f3f3f, cowWeightSum = 0;
bool compare(const Cow &a, const Cow &b)
{
    return (a.weight + a.strength) < (b.weight + b.strength);
}
bool operator<(const Cow &a, const Cow &b)
{
    return a.weight < b.weight;
}
void input()
{
    scanf("%d", &N);
    for (int i = 0; i < N; i++)
    {
        scanf("%lld%lld", &cows[i].weight, &cows[i].strength);
        cowWeightSum += cows[i].weight;
    }
    cows[N].weight = inf;
    cows[N].strength = inf;
    sort(cows, cows + N + 1, compare);
}
bool judge(ll mid)
{
    ll currentWeightSum = cowWeightSum - mid;
    priority_queue<Cow> que;
    int count = 0;
    int limit = N;
    while (count < N)
    {
        int next = lower_bound(cows, cows + N + 1, currentWeightSum, compare) - cows;
        if (next == N)
        {
            return false;
        }
        for (int i = next; i < limit; i++)
        {
            que.push(cows[i]);
        }
        limit = min(next, limit);
        if (que.empty())
        {
            return false;
        }
        Cow cow = que.top();
        que.pop();
        currentWeightSum -= cow.weight;
        count++;
    }
    return true;
}
void binarySearch()
{
    ll left = -1000000001, right = 500000000;
    while (left + 1 < right)
    {
        ll mid = (left + right) / 2;
        if (judge(mid))
        {
            right = mid;
        }
        else
        {
            left = mid;
        }
    }
    printf("%lld\n", right);
}
int main()
{
    input();
    binarySearch();
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务