zoukankan      html  css  js  c++  java
  • P2869 [USACO07DEC]美食的食草动物Gourmet Grazers

    P2869 [USACO07DEC]美食的食草动物Gourmet Grazers


    题目:约翰的奶牛对食物越来越挑剔了。现在,商店有M 份牧草可供出售,奶牛食量很大,每份牧草仅能供一头奶牛食用。第i 份牧草的价格为Pi,口感为Qi。约翰一共有N 头奶牛,他要为每头奶牛订购一份牧草,第i 头奶牛要求它的牧草价格不低于Ai,口感不低于Bi。请问,约翰应该如何为每头奶牛选择牧草,才能让他花的钱最少?


    题解:对奶牛的价格要求和草的价格要求进行排序,排序后可以得到如下:

    [egin {align} (A_1, B_1), (A_2, B_2), cdots, (A_N, B_N),~A_i ≤ A_j, ~1 ≤ i < j ≤ N \ (P_1, Q_1), (P_2, Q_2), cdots, (P_M, Q_M),~P_i ≤ P_j, ~1 ≤ i < j ≤ M end {align} ]

    从第一项开始遍0历,若((P_1, Q_1))可以使得(A_x < P_1 < A_{x + 1}),那么将((B_1, 1), cdots, (B_x, x))放入(S),因为这样可以将奶牛的需求按照品质排序,每次该牧草所给的奶牛的序号应该为(t),其中(Q_t ≤ Q_1 < Q_{t + 1}),即(t = S.lower\_bound(Q_1) - 1),但是我们会发现这存在问题,因为(lower\_bound)如果找不到,会定位在比(Q_1)大的那个数上,所以这里可以使用技巧:(S)进行降序排序(原来是升序),只需要将每个数乘上(-1)即可取出来的时候也乘(-1)。对于其后考虑的牧草,可以发现(P_i ≥ P_1)(已经排好序了),所以在(S)中的奶牛只需要关心品质,无需关心价格。

    综上所述我们可以发现是需要维护一个储存奶牛的(multiset),这其中在判断草是否可以用有一个技巧:直接使用迭代器(std::multiset ext{<}int ext{>}::iterator~~iter = cow\_set.lower\_bound(Q_{i}))。对于这个迭代器,由于放入集合中的是降序排列,我们只需要操作迭代器就可以确定一个草可不可以用。现在我们假设:一个草的品质低于现在集合中奶牛所需的最低品质,很显然这个时候返回的(iter)是不在集合当中的(因为默认找更大的一个),此时一定有(iter == cow\_set.end())(根据(end())的定义)。

    代码:

    #include <iostream>
    #include <algorithm>
    #include <set>
    
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100005;
    
    ll n, m;
    pair<ll, ll> cow[maxn], grass[maxn];
    multiset<ll> cow_set;
    
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= n; i ++)
            cin >> cow[i].first >> cow[i].second;
        for (int i = 1; i <= m; i ++)
            cin >> grass[i].first >> grass[i].second;
        sort(cow + 1, cow + 1 + n);
        sort(grass + 1, grass + 1 + m);
    
        ll ans = 0;
        for (int grass_i = 1, cow_i = 0; grass_i <= m; grass_i ++) {
            ll now_grass_cost = grass[grass_i].first;
            ll now_grass_quality = grass[grass_i].second;
            for (int i = cow_i + 1; i <= n && cow[i].first <= now_grass_cost; i ++) {
              	// 符号:将序排列
                cow_set.insert(-cow[i].second);
                cow_i ++;
            }
            set<ll>::iterator iter = cow_set.lower_bound(-now_grass_quality);
     				// 草品质达到
          	if (iter != cow_set.end()) {
                cow_set.erase(iter);
                ans += now_grass_cost;
            }
        }
      	// 如果还有牛剩下来 -> 这些牛的要求没有被满足 -> 答案为-1 
        if (!cow_set.empty()) ans = -1;
        cout << ans << endl;
    }
    
  • 相关阅读:
    课件的引子
    用nc做网络压力测试
    分布式计算学习笔记
    静态库 .a 转成共享库 .so
    nmon用法
    eclipse debug URLClassPath.getLoader(int) file
    sodu 命令场景分析
    俩孩随笔
    深度学习丨深度学习中GPU和显存分析
    语义分割丨DeepLab系列总结「v1、v2、v3、v3+」
  • 原文地址:https://www.cnblogs.com/jeffersonqin/p/11210922.html
Copyright © 2011-2022 走看看