1. 程式人生 > >Codeforces-985C

Codeforces-985C

題解連結

題目連結

題目

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 (1n,k105,1n·k105,0l109).

The second line contains m = n·k space-separated integers a1,a2,...,am (1ai109) — 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

|vxvy|l for any 1 ≤ x ≤ n and 1 ≤ y ≤ n.

題意

  需要造n個桶,每個桶需要k個木板,任意兩個桶之間容積(一個桶中最短的木板的高度)的差距不能超過l,然後給你n * k個木板,第i個木板的長度為ai,問能否造出符合條件的n個桶,如果能的話問這n個桶的容積之和最大是多少,如果不能的話就輸出0

思路

  首先對所有木板sort一下,由於短板效應,我們至少可以讓前n個木板恰好為n個桶的容積,判斷一下ana1l是否成立,不成立的話一定是0,因為前n個的木板的差距一定是最小的。

  我們發現,如果我們讓每連續的k個木板形成一個桶的話,那麼這些桶的容積將會是a1ak+1a2k+1,中間一些較小的木板都會被更短但是又必須得取的木板給包含,這樣一定是最優的。

  首先我們找到一個最大的upper,使得auppera1l(uppern·k)成立,這樣在[1,upper]的範圍內以任意n個木板的高度為桶的容積都是合法的。假設此時我們選了x個連續的k來造桶,還需要再造y個桶才能造夠n個桶,則有:

x·k+yupperx+y=n

  移項、代入、化簡:

xuppernk1

  也就是說:得到x後,y也就相應出來了,對於剩下的upperx·k個木板,顯然取後y1個和第x·k+1個木板作為剩下的y個桶的容積是最優的。

實現

#include <bits/stdc++.h>
typedef long long ll;
const int maxn = int(1e5) + 7;
ll n, k, l, m, a[maxn], ans, upper;
int main() {
    scanf("%lld%lld%lld", &n, &k, &l);
    m = n * k;
    for (ll i = 1; i <= m; i++) scanf("%lld", a + i);
    std::sort(a + 1, a + 1 + m);
    if (a[n] - a[1] > l) return 0 * puts("0");
    if (k == 1) for (ll i = 1; i <= n; i++) ans += a[i];
    else {
        while (a[upper] - a[1] <= l && upper <= m) upper++;
        upper--;
        ll x = (upper - n) / (k - 1);
        for (ll i = 1, cur = 1; i <= x; i++, cur += k) ans += a[cur];
        for (ll i = 1; i < n - x; i++) ans += a[upper--];
        ans += a[x * k + 1];
    }
    printf("%lld\n", ans);
    return 0;
}