牛客:合并序列(二分+贪心)
题意:
链接: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); } }