P2869 [USACO07DEC]Gourmet Grazers G

· · 题解

这道题目是溢水的蓝题(毕竟用 multiset 做就是如此)!!

思路

这道题我们通过排序来削掉口感那个指标!

首先,我们定义一个结构体(方便排序)

struct A{
    int a,b,c;//a、b为题目中的意思,c=0表示当前的为牛,相反,c=1表示当前的为干草
}a[200010];

再定义一个可重集 multiset

multiset<int>s;

所以我们先把草和牛按照口感从大到小排序

bool cmp(A a,A b){
    if(a.b==b.b)
        return a.c>b.c;
    return a.b>b.b;
}
sort(a+1,a+n+1,cmp);

我们再从前往后遍历排序后的数组

  1. 如果遇到了草,我们把它的价钱加进 multiset

    if(a[i].c==1)
    s.insert(a[i].a);
  2. 如果遇到了牛,由于我们的第二个指标也就是口感满足一定大于等于当前牛的口感,所以不用管,毕竟我们已经排过序了(成功削掉一个指标)。然后我们呢再通过 multiset 的一系列操作得到最小的大于等于当前所需价钱的干草。

else{
    set<int>::iterator it=s.lower_bound(a[i].a);
    if(s.empty()||it==s.end()){
        cout<<-1<<endl;
        return 0;
    }
    ans+=*it;
    s.erase(it);
}

最后输出所有干草价钱的和即可

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
struct A{
    int a,b,c;
}a[200010];
int n,m,ans;
multiset<int>s;
bool cmp(A a,A b){
    if(a.b==b.b)
        return a.c>b.c;
    return a.b>b.b;
}
signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&a[i].a,&a[i].b);
        a[i].c=0;
    }
    n+=m;
    for(int i=n-m+1;i<=n;i++){
        scanf("%lld%lld",&a[i].a,&a[i].b);
        a[i].c=1;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        if(a[i].c==1)
            s.insert(a[i].a);
        else{
            set<int>::iterator it=s.lower_bound(a[i].a);
            if(s.empty()||it==s.end()){
                cout<<-1<<endl;
                return 0;
            }
            ans+=*it;
            s.erase(it);
        }
    }
    cout<<ans<<endl;
}