Codeforces 985C (貪心)
題面:
C. Liebig's Barrelstime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputYou 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
Print maximal total sum of volumes of equal enough barrels or 0 if it's impossible to satisfy the condition above.
InputThe first line contains three space-separated integers n, k and l (1 ≤ n, k ≤ 105, 1 ≤ n·k ≤ 105, 0 ≤ l ≤ 109).
The second line contains m = n·k space-separated integers a
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.
ExamplesinputCopy4 2 1 2 2 1 2 3 2 2 3outputCopy
7inputCopy
2 1 0 10 10outputCopy
20inputCopy
1 2 1 5 2outputCopy
2inputCopy
3 2 1 1 2 3 4 5 6outputCopy
0Note
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塊木板組成,一個木桶的容水量為最短的木板的長度。先給你n*k塊木板的長度,問你在兩兩木桶的容積不超過l的條件下,組成n個桶能獲得的最大容積和是多少。
題目分析:
根據木桶原理我們可以得知,木桶的容積與長度很大的木板沒有任何關係。因此我們先將所有木桶的長度排序。因為要組成n個木桶,(在最差的情況下,我們的策略是第1個木板跟第n*k個木板組合,第2個模板和第n*k-1個木板結合)。因此,首先我們先需要判斷第n塊木板和第一塊木板的長度。倘若這兩塊木板的差值已經是大於l了,則表明必定無法構成n個桶,故輸出0。
而倘若上述兩塊小於等於l,則此時需要採用貪心的策略。因為我們需要得到最大的容積,因此,我們需要儘可能貪心地將上界提高。因此我們需要在所有木板中找到第一個與第一塊木板長度差大於l的木板,然後在計算容積的過程中,儘可能地讓長度短的木板優先形成木桶,進而使得長度大的木板對結果有貢獻,從而使得答案的結果最大。
程式碼:
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long ll;
ll a[maxn];
int main()
{
ll n,k,l;
cin>>n>>k>>l;
for(int i=0;i<n*k;i++){
cin>>a[i];
}
sort(a,a+n*k);
if(a[n-1]-a[0]>l){
puts("0");
return 0;
}
ll rn;
rn=lower_bound(a,a+n*k,a[0]+1+l)-a;//計算出第一個與第一塊木板相差l的木板的編號
ll cnt=rn-n;//計算出能夠跳調多少塊板
ll ln=0;
ll res=0;
for(int i=0;i<n;i++){
res+=a[ln];
if(cnt>=k-1){//如果能跳過的板子正好可以組成一個木桶,則將左指標右移k-1
cnt-=k-1,ln+=k-1;
}
else if(cnt){//否則直接將左指標移動cnt位,同時清零
ln+=cnt;
cnt=0;
}
ln++;
}
cout<<res<<endl;
return 0;
}