2021牛客暑期多校训练营6 F. Hamburger Steak(贪心/好题)

链接:https://ac.nowcoder.com/acm/contest/11257/F
来源:牛客网

题目描述

Riko is ready to cook hamburger steaks. There are mm pans and nn hamburger steaks that need to be fried. The ii-th hamburger steak needs to be fried for titi (which is a positive integer) minutes. Riko can fry it in a certain pan for titi minutes, or in two different pans for aiai and bibi minutes respectively, where aiai and bibi are both positive integers and ai+bi=tiai+bi=ti. Riko will start cooking at time 00 and she wants to finish cooking as soon as possible. Please help Riko make a plan to minimize the time spent cooking all the hamburger steaks.

In this problem, we assume that a pan can fry at most one hamburger steak at the same time, and a hamburger steak can be put in at most one pan at the same time. Different pans can fry different hamburger steaks at the same time. We also assume that it takes no time to put a hamburger steak in a pan or take it out.

输入描述:

The first line of the input contains two integers nn and m (1≤n,m≤105)m (1≤n,m≤105).

The second line contains nn integers t1,t2,…,tn (1≤ti≤109)t1,t2,…,tn (1≤ti≤109).

输出描述:

Output nn lines. The ii-th line describes the cooking plan for the ii-th hamburger steak.


Each line begins with an integer k (k∈{1,2})k (k∈{1,2}), representing that Riko will fry the hamburger steak in kk pans. Then there follow kk integer triples id,l,r (1≤id≤m, 0≤l<r≤1018)id,l,r (1≤id≤m, 0≤l<r≤1018) in chronological order, representing that Riko will fry the hamburger steak in the pan numbered idid during time [l,r)[l,r).

If there are multiple answers, output any.

示例1

输入

复制

5 3
1 2 3 4 5

输出

复制

1 1 0 1
1 2 0 2
1 2 2 5
1 1 1 5
1 3 0 5

我是沙比, GG。还好队友偷偷把这个题A了。

由于木桶效应,花费的最小时间等于最优方式下用时最长的那个锅的时间。如果我们知道了最小时间,那么贪心地安排煎每个小汉堡的时间。

首先,最终答案的最小耗时肯定不会小于最大的汉堡的ti。因为每一时刻汉堡只能在一个锅,如果最小耗时小于最大的煎汉堡时间,那么一定会有某一时刻这个小汉堡同时出现在两个锅里,矛盾。这样我们贪心的基础就有了,即对于每个汉堡先放到当前的锅,如果时间没超的话就在这个锅煎完,否则就把这个汉堡在这个锅煎到最大时间,剩余的在下一个锅煎。因为最终答案的最小耗时肯定不会小于最大的煎肉饼时间,因此这样能保证分两次煎的汉堡的两段时间没有交集(画个图就明白了)。那么问题就变成了怎么求总的最小耗时。一个显然的思路就是二分这个最小时间,n取1e5,二分答案的值域是1e18的话是可以通过的。但二分实际上没有必要。最小时间需要同时满足两个条件:所有锅的时间和大于等于所有汉堡的时间和,以及耗时最长的汉堡排不会在同一时刻分到两个锅中(这个和前面提到的条件是一样的),因此最小时间就是(max(max_{i = 1}^{n}t_i, lceil frac{sum}{m} ceil))

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, m, t[100005];
signed main() {
    cin >> n >> m;
    int sum = 0, mx = 0, tmax = 0;
    for (int i = 1; i <= n; i++) {
        cin >> t[i];
        mx = max(mx, t[i]);
        sum += t[i];
    }
    tmax = max(mx, (sum + m - 1) / m);
    int nowpan = 1, nowtime = 0;
    for (int i = 1; i <= n; i++) {
        if (nowtime == tmax) {
            nowtime = 0;
            nowpan++;
        }
        if (nowtime + t[i] <= tmax) {
            cout << 1 << " " << nowpan << " " << nowtime << " " << nowtime + t[i] << endl;
            nowtime += t[i];
        } else {
            cout << 2 << " ";
            cout << nowpan + 1 << " " << 0 << " " << t[i] - (tmax - nowtime) << " ";
            cout << nowpan << " " << nowtime << " " << tmax << endl;
            nowpan++; nowtime = t[i] - (tmax - nowtime);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lipoicyclic/p/15092342.html