Liebig's Barrels CodeForce菚985 C題解[C+]
タイトルソース
http://codeforces.com/contest/985/problem/C
題意分析
You have m̵n・k wooden staves.The i-th stave has length ai.You have to asemble n barrels consisting of k staves each,You can use any k staves to construct.Each stave mberriel.excleat.barrout
Let volume v j of barrel j be equal to the length of the minimal stave in it.
You want to assieble 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 reulting barrels mut exced. for any 1̵≦̵x?≦?n and 1̵≦̵y?≦?vx̵−v y?≦?l f o r a n y 1̵≦̵x?≦?n a n d 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≦?105,1̵≦?n≦?n≦?̵≤?l?? a n d l(1̵≦̵n,?k≦?10,1̵≦̵n・k?10,0?≦̵l?̵10).
The second line contains m(8201)=n・k space-separated integersa 1,_;a2,?…,?am(1̵≦?ai?̵̵̵̵̵̵̵̵̵109 1;̵̵109 1;̵109 1;̵̵̵109 1;̵
Output
Print single integer-maximal total sum of the volumes of barrels or 0 if it's impossible to construct exactly n barrels the condition̵vy for any 1̵≦̵x?≦?n and 1̵≦̵y?≦?vx̵−v y?≦?l f o r a n y 1̵≦̵x?≦?n a n d 1̵≦̵y?≦?n.
Sample Input
input
4 2 1
2 1 2 2 2 3 3
out put
7
input
2 1 0
10
out put
20
input
1 2 1
5 2
out put
2
input
3 2 1
1 2 3 4 5
out put
0
ノート
In the first example you can form the follwing barrels:[1,̵2],[2,̵2],[2,̵3],[2,̵3].
In the second example you can form the follwing barrels:[10],[10].
In the third example you can form the follwing barrels:[2,8201].
In the fourth example difference between volumes of barrels in any partition ist 2 so it is impossible to make barrels equal enough.
n*kブロックの板を与え、n個の板数kの樽を構成することが要求される.樽の容積は樽の最短の板に等しい.任意の2つの桶間の容積差は所定の閾値lより小さく、k個の樽の容積と最大になる.
問題を解く構想
この問題は一見ドラム缶のように見えるが、実はそうではない.
まず、問題の制約条件を考えます.つまり、任意の樽容積(最短板)の差が閾値より小さいです.それでは、すべての桶の一番短い木の板は一番短い木の板の中にしか現れないかもしれません.
そのため[m i n,min+l][m i n,m i n+l]に記入します.の板の数は、m.m.次の二つの状況に分けて検討します.1.m<k>の場合、任意の桶間の容積差がlより小さいことを満たすことができません.出力は0に戻ります.2.m>=k.この時、mブロックの板からkブロックをそれぞれの桶の一番短い板として選出します.樽の容積と最大にするために、できるだけ短い板を使用します.寄せ集めて同じ桶を形成します.このように少し長い板は他の桶の一番短い板に選ばれます.だからここでは貪欲な策略を使います.現在(未使用の)一番短い木の板とそれより長い木の板で樽を構成します.その中で一番短い木の板はこの桶の一番短い板として作られます.
-樽全体を構成しています.
-または残りの木の板の数は、最も短い板が確定されていない樽の数に等しい.
以上の分析によって、簡単に書き出すことができます.しかし、ここでは最適化もできます.私たちは[m i n,min+l][m i n,m i n+l]の板を探し出す必要があります.だから、私たちの任務はn*k全体を並べ替える必要はなく、変形の山を利用して並べ替えることができます.
つの小さい根のヒープを創立して、順次山の頂を弾いて保存します.現在の山の頂がすでにm i n+l m i n+lより大きいことを発見するまで.
コードの実装
http://codeforces.com/contest/985/problem/C
題意分析
You have m̵n・k wooden staves.The i-th stave has length ai.You have to asemble n barrels consisting of k staves each,You can use any k staves to construct.Each stave mberriel.excleat.barrout
Let volume v j of barrel j be equal to the length of the minimal stave in it.
You want to assieble 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 reulting barrels mut exced. for any 1̵≦̵x?≦?n and 1̵≦̵y?≦?vx̵−v y?≦?l f o r a n y 1̵≦̵x?≦?n a n d 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≦?105,1̵≦?n≦?n≦?̵≤?l?? a n d l(1̵≦̵n,?k≦?10,1̵≦̵n・k?10,0?≦̵l?̵10).
The second line contains m(8201)=n・k space-separated integersa 1,_;a2,?…,?am(1̵≦?ai?̵̵̵̵̵̵̵̵̵109 1;̵̵109 1;̵109 1;̵̵̵109 1;̵
Output
Print single integer-maximal total sum of the volumes of barrels or 0 if it's impossible to construct exactly n barrels the condition̵vy for any 1̵≦̵x?≦?n and 1̵≦̵y?≦?vx̵−v y?≦?l f o r a n y 1̵≦̵x?≦?n a n d 1̵≦̵y?≦?n.
Sample Input
input
4 2 1
2 1 2 2 2 3 3
out put
7
input
2 1 0
10
out put
20
input
1 2 1
5 2
out put
2
input
3 2 1
1 2 3 4 5
out put
0
ノート
In the first example you can form the follwing barrels:[1,̵2],[2,̵2],[2,̵3],[2,̵3].
In the second example you can form the follwing barrels:[10],[10].
In the third example you can form the follwing barrels:[2,8201].
In the fourth example difference between volumes of barrels in any partition ist 2 so it is impossible to make barrels equal enough.
n*kブロックの板を与え、n個の板数kの樽を構成することが要求される.樽の容積は樽の最短の板に等しい.任意の2つの桶間の容積差は所定の閾値lより小さく、k個の樽の容積と最大になる.
問題を解く構想
この問題は一見ドラム缶のように見えるが、実はそうではない.
まず、問題の制約条件を考えます.つまり、任意の樽容積(最短板)の差が閾値より小さいです.それでは、すべての桶の一番短い木の板は一番短い木の板の中にしか現れないかもしれません.
そのため[m i n,min+l][m i n,m i n+l]に記入します.の板の数は、m.m.次の二つの状況に分けて検討します.1.m<k>の場合、任意の桶間の容積差がlより小さいことを満たすことができません.出力は0に戻ります.2.m>=k.この時、mブロックの板からkブロックをそれぞれの桶の一番短い板として選出します.樽の容積と最大にするために、できるだけ短い板を使用します.寄せ集めて同じ桶を形成します.このように少し長い板は他の桶の一番短い板に選ばれます.だからここでは貪欲な策略を使います.現在(未使用の)一番短い木の板とそれより長い木の板で樽を構成します.その中で一番短い木の板はこの桶の一番短い板として作られます.
-樽全体を構成しています.
-または残りの木の板の数は、最も短い板が確定されていない樽の数に等しい.
以上の分析によって、簡単に書き出すことができます.しかし、ここでは最適化もできます.私たちは[m i n,min+l][m i n,m i n+l]の板を探し出す必要があります.だから、私たちの任務はn*k全体を並べ替える必要はなく、変形の山を利用して並べ替えることができます.
つの小さい根のヒープを創立して、順次山の頂を弾いて保存します.現在の山の頂がすでにm i n+l m i n+lより大きいことを発見するまで.
コードの実装
#include
#include
#include
using namespace std;
vector<long> entry;
int total;
void insert_heap(long current, int low, int high)
{
int small = 2 * low + 1;
while (small <= high) {
if (small < high&&entry[small] > entry[small + 1]) small++;
if (current <= entry[small]) break;
else {
entry[low] = entry[small];
low = small;
small = 2 * low + 1;
}
}
entry[low] = current;
}
void build_heap()
{
for (int low = total / 2 - 1; low >= 0; low--) {
long current = entry[low];
insert_heap(current, low, total - 1);
}
}
int main()
{
long n, k, threshold, temp;
long long tempAns = 0;
scanf("%ld%ld%ld", &n, &k, &threshold);
total = n*k;
for (int i = 0; i scanf("%ld", &temp);
entry.push_back(temp);
}
build_heap();
long last_unsorted, current, sst;
sst = entry[0];
long lst = sst + threshold;
for (last_unsorted = total - 1; last_unsorted > 0; last_unsorted--) {
current = entry[last_unsorted];
if (entry[0] > lst) break;
entry[last_unsorted] = entry[0];
insert_heap(current, 0, last_unsorted - 1);
}
if (entry[0] <= lst) last_unsorted = -1;
if (total - last_unsorted - 1 < n) {
printf("0
");
return 0;
}
int j, buckets = 0;
long long ret = 0;
int p = total - 1;
for (int i = 1; i <= n; i++) {
ret += entry[p--];
for (int j = 1; j <= k - 1; j++) {
if ((p - last_unsorted + i) <= n) break;
else p--;
}
}
printf("%I64d
", ret);
return 0;
}
コード表現