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);
我们再从前往后遍历排序后的数组
-
如果遇到了草,我们把它的价钱加进
multiset里if(a[i].c==1) s.insert(a[i].a); -
如果遇到了牛,由于我们的第二个指标也就是口感满足一定大于等于当前牛的口感,所以不用管,毕竟我们已经排过序了(成功削掉一个指标)。然后我们呢再通过
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;
}