• codeforces 985C Liebig's Barrels


    题意:

    有n * k块木板,每个木桶由k木板组成,每个木桶的容量定义为它最短的那块木板的长度。

    任意两个木桶的容量v1,v2,满足|v1-v2| <= d。

    问n个木桶容量的最大的和为多少,或者说明不可能做出这样的n个木桶。

    思路:

    贪心

    要满足|v1-v2| <= d,那么就要满足最大的木桶容量和最小的木桶容量的差小于等于d。

    所以先把木板长度排序,如果a[0] 到 a[0] + d这个范围内有大于等于n个木板,那么就存在合理的分配方案,因为可以把至少n个木板作为最短的木板。

    然后就计算最大的和,如果a[0] 到 a[0] + d这个范围内刚好有n块木板,那么最大的和就是这n块木板长度的和;

    如果大于n的话,那么就要考虑让每个木桶最小木板的长度尽可能的大,就是让每个最小木板尽选择数组后面的数字。

    因为1块木板可以支配k - 1块木板,所以下一个木桶的最小长度就可以从a[k]开始,这样就让最小的尽量大了。

    一个木板可以覆盖的区间长度是k,假设a[0] 到 a[0] + d这个范围内有sum块木板,那么多余的木板就是res = sum - n。

    区间数量就是c = res / (k-1),设r = res % (k - 1),

    当r = 0,那么就有c个完整的区间,前c个木桶的长度就是0*k,1*k,2*k . . . (c-1)*k,后n - c个木桶的容量的下标就从c * k到sum-1;

    当r != 0,有c个完整的区间和一个不完整的区间,前c + 1个木桶的容量就是0 * k,1 * k,2 * k . . . c * k,后n - c - 1个木桶的容量的下标就从c * k + r + 1到sum - 1。

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N = 1e5 + 10;
     6 long long a[N];
     7 int main()
     8 {
     9     int n,k;
    10     long long l;
    11     scanf("%d%d%lld",&n,&k,&l);
    12     for (int i = 0;i < n * k;i++) scanf("%lld",&a[i]);
    13     sort(a,a+n*k);
    14     //printf("%lld
    ",a[0] + l);
    15     int pos = upper_bound(a,a+n*k,a[0] + l) - a;
    16     pos--;
    17     //printf("%d
    ",pos);
    18     if (pos < n - 1) puts("0");
    19     else
    20     {
    21         long long ans = 0;
    22         int sum = pos + 1;
    23         if (sum == n)
    24         {
    25             for (int i = 0;i < n;i++) ans += a[i];
    26         }
    27         else
    28         {
    29             if (k == 1)
    30             {
    31                 for (int i = 0;i < n;i++) ans += a[i];
    32             }
    33             else
    34             {
    35                 int c = (sum - n) / (k - 1);
    36                 int r = (sum - n) % (k - 1);
    37                 if (r)
    38                 {
    39                     for (int i = 0;i <= c;i++)
    40                     {
    41                         ans += a[i*k];
    42                     }
    43                     n -= c + 1;
    44                     for (int i = k * c + r + 1;i <= pos;i++)
    45                     {
    46                         if (n == 0) break;
    47                         ans += a[i];
    48                         n--;
    49                     }
    50                 }
    51                 else
    52                 {
    53                     for (int i = 0;i < c;i++)
    54                     {
    55                         ans += a[i*k];
    56                     }
    57                     n -= c;
    58                     for (int i = k * c;i <= pos;i++)
    59                     {
    60                         if (n == 0) break;
    61                         ans += a[i];
    62                         n--;
    63                     }
    64                 }
    65             }
    66         }
    67         printf("%lld
    ",ans);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    0. 序列
    Megacli 常用
    4. Storm可靠性
    3. Storm编程框架
    2. Storm消息流
    1.1 Storm集群安装部署步骤
    poj3723,最 大 生成树
    次短路
    无间道之并查集
    最小生成树二Kruscal算法
  • 原文地址:https://www.cnblogs.com/kickit/p/9070612.html
Copyright © 2020-2023  润新知