1. 程式人生 > >Educational Codeforces Round 44 (Rated for Div. 2) C

Educational Codeforces Round 44 (Rated for Div. 2) C

題目連結:http://codeforces.com/contest/985/problem/C 很簡單的一道題目,但是想了半天還把自己氣得要死,因為又讀錯題意了。。 題意: 給你3個數,n,k,l,再給你n*k的a[],表示叫你湊n個木桶出來,木桶的長度取決於最小的a,最終的n個木桶最大和最小的差值不超過l,問這些木桶長度加起來最長有多少。 那麼我們先排個序,如果第n個數和第1個數的差值都大於l了,那麼就是不可能的。之後要分是不是1的情況,為什麼要分情況呢?接下來會講到。 sort完之後我們for一遍看看能與a[1]相距l的最大的位置在哪裡。記做cnt,那麼我們的任務是在這cnt個數裡面取出合法且最大的n個數,那麼我們先可以得到有cnt-n個數是可以不當做最低點的,那麼我們儘量用最小的去和最小的配,為什麼? 如果是1 1 2 2 的話,k=2,l=1的時候,當然是11,22是最大的,12,12是最小的,這個想想就知道了。所以有(cnt-n)/(k-1)個數是可以當做被匹配的木板。然後不一定cnt-n個數都能匹配的上,最後可能有剩餘,那麼就是n-(cnt-n)/(k-1)-1個數了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100005];
int main()
{
    int n,k,l,m;
    scanf("%d%d%d",&n,&k,&l);
    m=n*k;
    for(int i=1;i<=m;i++)
        scanf("%lld",&a[i]);
    sort(a+1,a+1+m);
    if(a[n]-a[1]>l)
        printf("0\n");
    else
if(k==1) { ll ans=0; for(int i=1;i<=n;i++) ans+=a[i]; printf("%lld\n",ans); } else { int cnt=1; while(a[cnt]-a[1]<=l&&cnt<=m) cnt++; cnt--; int pos=(cnt-n)/(k-1); ll ans=0; for
(int i=1,j=1;i<=pos;i++,j+=k) ans+=a[j]; ans+=a[pos*k+1]; for(int i=1;i<n-pos;i++) ans+=a[cnt--]; printf("%lld\n",ans); } return 0; }