CodeForces 767 D.Cartons of milk(贪心)

Description

一个人一天要喝 k k 瓶牛奶,如果冰箱里的牛奶不够k瓶就全部喝完,目前冰箱里有 n n 瓶牛奶,给出每瓶牛奶的保质期,即还有几天会过期,过期的牛奶要被扔掉,再给出商店中m瓶牛奶的保质期,问是否存在一种方案使得这个人不扔掉任何一瓶牛奶,如果有,他最多可以从商店买多少瓶牛奶

Input

第一行三个整数 n,m,k n , m , k 表示已有牛奶数量,商店里牛奶数量和每天喝的牛奶数量,之后输入 n n 个整数f1,...,fn表示已有牛奶的保质期,最后 m m 个整数s1,...,sm表示商店里 m m 瓶牛奶的保质期

(1n,m106,1kn+m,0fi,si107)

Output

如果存在一种不用扔牛奶的方案则输出从商店里最多可以买多少瓶牛奶以及这些牛奶的编号,否则输出 1 − 1

Sample Input

3 6 2
1 0 1
2 0 2 0 0 2

Sample Output

3
1 2 3

Solution

ai a i 表示第 i i 天还可以喝的牛奶数量,把商店的m瓶牛奶按保质期排序,从第 107 10 7 天开始,对于第 i i 天,如果ai>k,那么多的牛奶只能放到之前喝,故把多余的 aik a i − k 瓶牛奶放到 ai1 a i − 1 ,如果 aik a i ≤ k ,那么只要 ai a i 不超过 k k ,且商店里还有保质期不小于i的牛奶,就可以一直从商店买牛奶放到第 i i 天喝,以此类推,如果最终a0>k,说明喝不完,无解,否则看是否可以接着从商店里买牛奶即可,时间复杂度 O(107+mlog2m) O ( 10 7 + m l o g 2 m )

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 11111111
int n,m,k,a[maxn];
typedef pair<int,int>P;
P b[maxn];
vector<int>ans;
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        ans.clear();
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<n;i++)
        {
            int temp;
            scanf("%d",&temp);
            a[temp]++;
        }
        for(int i=1;i<=m;i++)scanf("%d",&b[i].first),b[i].second=i;
        sort(b+1,b+m+1);
        int j=m;
        for(int i=10000000;i;i--)
        {
            if(a[i]>k)
            {
                a[i-1]+=a[i]-k;
                continue;
            }
            while(j&&b[j].first>=i&&a[i]<k)ans.push_back(b[j].second),a[i]++,j--;
        }
        if(a[0]>k)printf("-1\n");
        else
        {
            while(j&&a[0]<k)
                ans.push_back(b[j].second),a[0]++,j--;
            printf("%d\n",ans.size());
            sort(ans.begin(),ans.end());
            for(int i=0;i<ans.size();i++)
                printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值