CF985C Liebig's Barrels(贪心)(来自洛谷)

洛谷地址:https://www.luogu.com.cn/problem/CF985C

题意:

你有一共m=n*k个木板。第i个木板的长度为ai。你必须用其中的每k条木板组成n个木桶。每条木板只能且必须属于一个木桶。我们把第j个木桶的最短的木板长度作为这个木桶的容积vj

你想要让这组合起来的n个木桶总容积最大。但是你需要让他们的容积尽量差不多,使得无论那两个木桶的容积差不超过l,即|vx-vy|<=l(1<=vx,vy<=n)。

输出这n个尽量相等的木桶的最大容积。如果无法组成满足要求的n个木桶,输出“0”

输入格式

第一行包括三个分开的整数n,k,l(1<=n,k<=10^5, 1<=n·k<=10^5, 0<=l<=10^9)

第二行包括m=n*k个整数,表示木板长度a1,a2,...,am ( 1<=ai<=10^9)

输出格式

输出一个整数,即n个满足要求的木桶的容积最大值

输入输出样例

输入 #1
4 2 1
2 2 1 2 3 2 2 3
输出 #1
7
输入 #2
2 1 0
10 10
输出 #2
20
输入 #3
1 2 1
5 2
输出 #3
2
输入 #4
3 2 1
1 2 3 4 5 6
输出 #4
0

说明/提示

In the first example you can form the following barrels: [1,2][1,2] , [2,2][2,2] , [2,3][2,3] , [2,3][2,3] .

In the second example you can form the following barrels: [10][10] , [10][10] .

In the third example you can form the following barrels: [2,5][2,5] .

In the fourth example difference between volumes of barrels in any partition is at least 22so it is impossible to make barrels equal enough.

解析:

注意,这个木板选择,是可以不连续的

首先对木板高度进行从小到大的排序

1:我们先考虑容积最小的情况:

n个木桶,对每个木桶的最短处,取a[1]~a[n],是最小的情况,此时最大差值为:a[n]-a[1],如果这个值>l,那么不管怎么组合,都是不能满足题意的。

那么直接输出0即可。

2:不管怎么组合,a1一定是某个木桶的容积,那么从这里入手,从前往后找到a[p]-a[1]<=l&&a[p+1]-a[1]>l

容积最大取到i=p处,p和末尾k-1个组合,即n*k-k+2到n*k,p-1处再和后第2*(k-1)个组合,依次类推。

如果p后的木板不够用了,就从i=1从前往后每隔k个取1个即可。

#include<cstdio>
#include<stack>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
priority_queue<int,vector<int>,greater<int> > q;//优先为小的优先队列 
typedef long long ll;
const int maxn=1e5+20;
ll a[maxn];
struct node
{
    int x,id;
}st[maxn];
bool cmp(node a , node b)
{
    if(a.x==b.x)
        return a.id<b.id;
    return a.x<b.x;
}
int main()
{    // 4 0 20
    ll n,k,l;
    cin>>n>>k>>l;
    for(int i=1;i<=n*k;i++)
        cin>>a[i];
    sort(a+1,a+1+n*k);
    if(a[n]-a[1]>l)
        cout<<"0"<<endl;
    else
    {
            ll sum=0;
            int p=n*k;
            while(a[p]-a[1]>l)
                p--;
            int num=0;
            int md=p;
            for(int i=n*k;i-(k-1)>p;i-=(k-1))
            {
                sum+=a[md--];
                num++;    
            }
            for(int i=1;i<=(p-num);i+=k)
                sum+=a[i];
            cout<<sum<<endl;        
    }

}

 

posted @ 2020-07-10 21:01  liyexin  阅读(200)  评论(0编辑  收藏  举报