牛客:合并序列(二分+贪心)

题意:

链接:https://ac.nowcoder.com/acm/contest/7528/D
来源:牛客网

有一个长度为𝑛的非负整数数组𝑎[1..𝑛]和一个大于1的正整数𝑘。
你每次可以选不超过𝑘个数,删掉这𝑘个数然后往数组里加入这𝑘 个数的和,
进行一次这样的操作的代价是这𝑘个数的和。
求最小的𝑘使得合并成1个数的最小代价小于等于𝑇。
你输出的𝑘要大于等于2。

题解:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
ll a[maxn];
ll n,t;
int check (int mid) {
    priority_queue<ll,vector<ll>,greater<ll> > q;
    int tt=(n-1)%(mid-1)+1;
    ll sum=0;
    for (int i=1;i<=tt;i++) sum+=a[i];
    q.push(sum);
    for (int i=tt+1;i<=n;i++) q.push(a[i]);
    while (1) {
        if (q.size()<=mid) {
            if (q.size()>1) while (q.size()) {
                sum+=q.top();
                q.pop();
            }
            break;
        } 
        ll tt=0;
        for (int i=1;i<=mid;i++) {
            tt+=q.top();
            q.pop();
        }
        q.push(tt);
        sum+=tt;
    }

    return sum<=t;
}
int main () {
    while (~scanf("%lld%lld",&n,&t)) {
        for (int i=1;i<=n;i++) scanf("%lld",a+i);
        sort(a+1,a+n+1);
        int l=2,r=n;
        int ans=2;
        while (l<=r) {
            int mid=(l+r)>>1;
            //printf("1\n");
            if (check(mid)) {
                ans=mid;
                r=mid-1;
            } 
            else {
                l=mid+1;
            }
        }
        
        printf("%d\n",ans);
    }
}

 

posted @ 2020-09-14 19:32  zlc0405  阅读(135)  评论(0编辑  收藏  举报