BZOJ P1691 [Usaco2007 Dec] 挑剔的美食家 【贪心】【set】

这道题呢其实就一个十分普通的贪心,至于怎么实现就有很多种方法,由于用平衡树的人比较多,所以我在这里简单讲一下用#multiset#的做法。

简单谈一下心:我们可以分别将牛和草分别按照价格为第一关键字排序,然后我们在保证牛的价格小于等于当前草的价格的前提下,把牛要求的鲜嫩程度放在集合当中(集合是有序的),然后我们对于每一种草,我们只需要找到小于等于草的价格中牛需要的价格最大的,然后删除即可。

注意: p a i r < A , B > 的排序本身就是按照 A 为第一关键字排序的。

参考代码:

#include <set> 
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define SG string
#define DB double
#define LL long long
using namespace std;
const LL Max=1e5+5;
multiset<LL>Set;
multiset<LL>::iterator It;
pair<LL,LL>A[Max],B[Max];
LL N,M,Cur=1,Ans;
inline LL Read(){
    LL X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(LL X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
int main(){
    LL I,J,K;
    N=Read(),M=Read();
    for(I=1;I<=N;I++){
        A[I].first=Read(),A[I].second=Read();
    }
    sort(A+1,A+1+N);
    for(I=1;I<=M;I++){
        B[I].first=Read(),B[I].second=Read();
    }
    sort(B+1,B+1+M);
    for(I=1;I<=M;I++){
        while(Cur<=N&&A[Cur].first<=B[I].first){
            Set.insert(-A[Cur].second);Cur++;
        }
        It=Set.lower_bound(-B[I].second);
        if(It!=Set.end()){
            Ans+=B[I].first;Set.erase(It);
        }
    }
    if(Cur==N+1&&Set.size()==0){
        Write(Ans);
    } else {
        puts("-1");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81108314