cf Educational Codeforces Round 44 C. Liebig's Barrels

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tengfei461807914/article/details/81534706

原题:
C. Liebig’s Barrels
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You have m = n·k wooden staves. The i-th stave has length ai. You have to assemble n barrels consisting of k staves each, you can use any k staves to construct a barrel. Each stave must belong to exactly one barrel.

Let volume vj of barrel j be equal to the length of the minimal stave in it.

You want to assemble exactly n barrels with the maximal total sum of volumes. But you have to make them equal enough, so a difference between volumes of any pair of the resulting barrels must not exceed l, i.e. |Vx -Vy| ≤ l for any 1 ≤ x ≤ n and 1 ≤ y ≤ n.

Print maximal total sum of volumes of equal enough barrels or 0 if it’s impossible to satisfy the condition above.

Input
The first line contains three space-separated integers n, k and l (1 ≤ n, k ≤ 10^5, 1 ≤ n·k ≤ 10^5, 0 ≤ l ≤ 10^9).

The second line contains m = n·k space-separated integers a1, a2, …, am (1 ≤ ai ≤ 10^9) — lengths of staves.

Output
Print single integer — maximal total sum of the volumes of barrels or 0 if it’s impossible to construct exactly n barrels satisfying the condition |Vx - Vy| ≤ l for any 1 ≤ x ≤ n and 1 ≤ y ≤ n.

Examples
input
4 2 1
2 2 1 2 3 2 2 3
output
7
input
2 1 0
10 10
output
20
input
1 2 1
5 2
output
2
inputCopy
3 2 1
1 2 3 4 5 6
output
0
Note
In the first example you can form the following barrels: [1, 2], [2, 2], [2, 3], [2, 3].

In the second example you can form the following barrels: [10], [10].

In the third example you can form the following barrels: [2, 5].

In the fourth example difference between volumes of barrels in any partition is at least 2 so it is impossible to make barrels equal enough.

中文:
给你n×k个板子,每个板子长度为ai,现在让你把这n×k个板子分成n组,每组k个,每组当中取长度最小的值求和,且要求在这些组当中,任意取两组,两个组中各自的最小值相差不超过l,现在问你这个和最大是多少?

代码:

#include<iostream>
#include<limits>
#include<vector>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std;
typedef long long ll;

int n, k, l;
ll a[100001];

int main()
{
    ios::sync_with_stdio(false);
    while (cin >> n >> k >> l)
    {
        int ter = n*k;
        for (int i = 1; i <= ter; i++)
            cin >> a[i];

        sort(a + 1, a + 1 + ter);
        int ind = ter;
        for (int i = 2; i <= ter; i++)
        {
            if (a[i] - a[1]>l)
            {
                ind = i - 1;
                break;
            }
        }
        ll ans = 0;
        if (n == 1)
        {

            cout << a[1] << endl;
            continue;
        }

        if (ind<n)
        {
            cout << 0 << endl;
            continue;
        }

        if (k == 1)
        {
            for (int i = 1; i <= ind; i++)
                ans += a[i];
            cout << ans << endl;
            continue;
        }

        int res = ter - ind, pre = ind, flag = 1;

        for (int i = ind; i >= 1;)
        {
            if (res>0)
            {

                if (res >= (k - 1))
                {
                    res -= (k - 1);
                    ans += a[i];
                    i--;
                    pre = i;
                }
                else
                {
                    while ((pre - i + 1) + res<k)
                        i--;
                    ans += a[i];
                    flag = 0;
                    res = 0;
                }
            }
            else
            {

                if (flag != -1)
                {

                    if (flag!=0)
                        i++;
                    flag = -1;
                }
                i -= k;
                if (i<1)
                    break;
                ans += a[i];

            }
        }
        cout << ans << endl;

    }
    return 0;
}

思路:

要求所有组中最小值的和最大,听起来像是二分,贪心可以解决。那就是要让每组当中的最小值从最大的值开始选取即可。

首先从小到大排序,找到最后一个小于最小值加上l的下标ind,从ind向前依次取值作为每一组当中的最小长度,同时判断在下标ind后面是否有元素,如果有,尽量选取k个,与前面选取到的最小长度组成一组。

如果ind后面没有元素了,那么就一次从后向前组成一组即可。

例如
4 2 2
1 2 2 3 3 4 5 6

上面序列是排好序的,最小值是1,加上l=2以后是3。

那么ind值等于5

从ind向前依次选取最小元素与ind后面的值组成一组
[3,4]
[3.5]
[2,6]

4,5,6都被选抽走后,依次从后往前组成组即可

[1,2]

结果为9

猜你喜欢

转载自blog.csdn.net/tengfei461807914/article/details/81534706