[贪心] 二元组最小值最大

 CCPC省赛的时候和队友讨论了多值同时贪心怎么最优, 没整出来, 今天就碰到这种题了。。。

私以为贪心不是特别容易凭空构造出一种严谨/正确的贪心方案

我这种铁牌选手只能多看多学吧,没什么别的方法


题目:

给定N个二元组(a1,b1),(a2,b2),…,(aN,bN),请你从中选出恰好K个,使得ai的最小值与bi的最小值之和最大。

请输出ai的最小值与bi的最小值之和


解法:

先贪心一个值, 然后动态贪心第二个值, 类似二分答案

按a 或 b值从大到小排序

然后从前先后遍历, 维护一个答案小顶堆(里面是另一个值)

易证:若堆体积大于k 弹出的堆顶必然不是最优解,

当体积等于k时 堆顶必然是当前1 - now中 b值的范围最优解,

arr[now].fst 也是最优解 (开始已排序固定)

最后动态更新答案既为正确值


代码


const int MAXN = 1e6 + 10;
 
struct node
{
    ll fst, lst;
}arr[MAXN];
 
bool cmp(node a, node b)
{
    return a.fst > b.fst;
}

priority_queue <ll, vector<ll>, greater<ll> > PQ;
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);     cout.tie(0);
    //freopen("D://test.in", "r", stdin);
    //freopen("D://test.out", "w", stdout);
 
    ll n, k;
 
    cin >> n >> k;
 
    for(int i = 0; i < n; ++i)
    {
        cin >> arr[i].fst >> arr[i].lst;
    }
 
    sort(arr, arr + n, cmp);
    
    ll ans = -INF;

    for(int i = 0; i < n; ++i)
    {
        PQ.push(arr[i].lst);

        if(PQ.size() > k)
            PQ.pop();

        if(PQ.size() == k)
        {
            ans = max(ans, PQ.top() + arr[i].fst);
        }
    }
 
    cout << ans << '
';
 
    return 0;
}


原文地址:https://www.cnblogs.com/zeolim/p/12270381.html