题目:
卡路里
冰箱里有n种食物,第i种食物有mi cal(卡路里),以及含有vi营养物质。计算鸭制定了未来k天减肥计划,第j天最多摄入cj cal(卡路里),并且每天只吃一种食物。
问:计算鸭可以摄入营养物质的最大值是多少。
输入格式:
输入的第一行给出两个整数n,k,含义如题意所示;
接下来n行,每行两个整数mi,vi,含义如题意所示;
接下来k行,每行一个整数cj,含义如题意所示;
1≤ n,k≤ 3×1e5
1≤ mi,vi ≤ 1e6
1 ≤ cj ≤ 1e8
输出格式:
输出一个整数——表示计算鸭可以摄入的最多营养物质的含量。
输入样例:
3 2
1 65
5 23
2 99
10
2
输出样例:
164
思路:
根据题目分析,他只要求我们的营养最大和,所以我们完全可以将查询的循序进行重新排序,让限制卡路里最小(询问的卡路里数最小)的排在前面先处理,这样处理出来一定是最大营养值。然后从最小的开始遍历,把符合条件的食物放入堆中维护(是每次询问的时候再插入一部分,不要一开始就全部插入),因为卡路里要求小的,能吃这个食物,那么卡路里要求大的也能吃。
代码:
#include <iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=3e5+10;
typedef long long ll;
struct Node{
int x,y;
};
//重写比较函数(可以用pair)
bool cmp(const Node v,const Node w){
if(v.x!=w.x) return v.x<w.x;
return false;
}
int op[N];
Node arr[N];
void Solved() {
int n,k;
cin>>n>>k;
//堆
priority_queue<int> heap;
for(int i=0;i<n;i++){
int a,b;
cin>>a>>b;
arr[i]={a,b};
}
//将食物按,卡路里从小到大排序
sort(arr,arr+n,cmp);
ll sum=0;
for(int i=0;i<k;i++){
cin>>op[i];
}
//将询问也从小到大排序
sort(op,op+k);
//k次询问每次把符合条件的食物,全部丢进堆里面。
int idx=0;
for(int i=0;i<k;i++){
int tar;
tar=op[i];
//找符合条件的食物
while(idx<n&&arr[idx].x<=tar) {
heap.push(arr[idx].y);
idx++;
}
//没次取出符合条件,且营养最大的
if(!heap.empty()){
sum+=heap.top();
heap.pop();
}
}
cout<<sum<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
t=1;
while(t--) {
Solved();
}
return 0;
}