题解:AT_discovery_2016_final_b DDPC特別ビュッフェⅡ
题目大意
给你 \(n\) 碟菜,第 \(i\) 碟菜有 \(a_i\) 的价值,在 \(t_i\) 秒时,这碟菜会消失。
初始 \(0\) 秒,你可以用 \(1\) 秒的时间吃掉一碟菜,但如果这碟菜消失了,就不能吃。
也就是说,当前时间为 \(s\) 秒,若 \(s+1 \le t_i\),则你可以吃掉第 \(i\) 碟菜,\(s\) 变为 \(s+1\)。
当吃掉的菜价值总和不小于 \(m\) 时,你就吃饱了。
求你最少几秒才能吃饱(可能不能吃饱,无解)。
解题思路
考虑贪心,每秒钟取当前价值最高的菜。
发现很容易 Hack。
比如:\(n=2,m=3,a={1,2},t={1,2}\)。
这样就会先吃掉第 \(2\) 盘菜,然后第 \(1\) 盘菜就消失了,贪心策略失败。
发现其实可以反悔贪心,优先吃快消失的菜。
当前菜已消失时,就可以将过去吃过价值最低的菜替换为当前菜,即反悔。
最后把吃掉的多余的菜去掉,剩下菜的数量即为答案。
代码
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<string>
#include<bitset>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e5+10;
const int N=1e5;
const int INF=0x3f3f3f3f;
const long long LINF=0x3f3f3f3f3f3f3f3f;
int n,m;
struct node{
int t,val;//菜的消失时间和价值
}a[MAXN];
bool cmp(node x,node y){
return ((x.t<y.t)|(x.t==y.t&&x.val>y.val));
}
priority_queue < int,vector<int>,greater<int> > q;
signed main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].t);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
}
sort(a+1,a+1+n,cmp);//贪心,先按消失时间排序
int tim=0;//当前时间
long long sum=0;//价值总和
for(int i=1;i<=n;i++)
{
if(tim+1<=a[i].t){//够吃得下当前菜
sum+=a[i].val;
q.push(a[i].val);
tim++;
}
else if((!q.empty())&&(q.top()<a[i].val)){//不够吃下当前菜,返回
sum-=q.top();
sum+=a[i].val;
q.pop();
q.push(a[i].val);
}
}
if(sum<m){
puts("-1");
return 0;
}
while(sum-q.top()>=m)//把吃掉的多余的菜去掉
{
tim--;
sum-=q.top();
q.pop();
}
printf("%d\n",tim);
return 0;
}

浙公网安备 33010602011771号