1. 程式人生 > >codeforces 985C Liebig's Barrels

codeforces 985C Liebig's Barrels

排序 最大 codeforce printf 區間和 main amp else ace

題意:

有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\n",a[0] + l); 15 int pos = upper_bound(a,a+n*k,a[0] + l) - a; 16 pos--; 17 //printf("%d\n",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\n",ans); 68 } 69 return 0; 70 }

codeforces 985C Liebig's Barrels