codeforces 985C. Liebig's Barrels

n表示桶的个数,k表示每个桶的木板数目,l表示任意两个桶中的最短木板的差值的上限。

思路比较明确,找出最短木板的长度记为 m,那么每个桶的最短木板的范围在[ m,m+l]之间。、

在计算和的时候,思路有点混乱,始终没有找到正确的方法。

其实可以这样想:

  • 如果长度小于m+l的木板数目小于n,那么无解
  • 如果正好等于,就是前n个木板的和
  • 如果长度小于m+l的木板数目大于n,就需要跳过一些木板,同时要保证最后的和是最大的

针对第三种情况,枚举n个水桶,每个水桶最多跳过k-1个木块,同时保证剩下的范围在[ m,m+l ]之间的木板的个数可以分给剩下的水桶

        int ptr=0;
        for(int i=0;i<n;i++){
            sum+=stave[ptr++];
            for(int v=0;v<k-1;v++){
                if(pos-ptr>n-i-1)ptr++;
                else break;
            }
        }

非常简短巧妙的代码

整题的代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<unordered_map>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
using namespace std;
const int MAXN=1e5+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
ll stave[MAXN];
int n,k,l;
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&k,&l);
    int t=n*k;
    ll m;
    for(int i=0;i<t;i++){
        scanf("%I64d",&stave[i]);
        m=min(m,stave[i]);
        m=i==0?stave[i]:min(stave[i],m);
    }
    ll M=m+(ll)l;
    sort(stave,stave+t);
    int pos=upper_bound(stave,stave+t,M)-stave;
    if(pos<n)printf("%d\n",0);
    else {
        ll sum=0;
        int ptr=0;
        for(int i=0;i<n;i++){
            sum+=stave[ptr++];
            for(int v=0;v<k-1;v++){
                if(pos-ptr>n-i-1)ptr++;
                else break;
            }
        }
        printf("%I64d\n",sum);
    }
}

 

posted @ 2018-09-28 18:53  MalcolmMeng  阅读(198)  评论(0编辑  收藏  举报