题意: 给定nnn种花,第iii种有aia_iai?朵,一束花由mmm朵互不相同种类的花组成,问最多可以组成多少束花。
数据范围:1≤n,m≤3×105,1≤ai≤1091\leq n,m\leq 3\times10^5,1\leq a_i\leq 10^91≤n,m≤3×105,1≤ai?≤109
题解: 二分答案,设当前答案为xxx,判断答案是否合法,合法则真实答案至少为xxx,否则真实答案至多为x?1x-1x?1。判断条件是每种花取ci=min(x,ai)c_i=min(x,a_i)ci?=min(x,ai?),最后判断sum≥∑cisum \geq \sum c_isum≥∑ci?是否成立即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<cmath>
using namespace std;typedef long long ll;template<typename T>
inline T Read(){
T s = 0, f = 1; char ch = getchar();while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();}while(isdigit(ch)) {
s = (s << 3) + (s << 1) + ch - '0'; ch = getchar();}return s * f;
}#define read() Read<int>()
#define readl() Read<long long>()const int N = 3e5 + 10;
int a[N];
int n, m;bool check(int x) {
ll sum = 0;for(int i = 1; i <= n; i++) sum += min(x, a[i]);return sum >= 1ll * x * m;
}void solve() {
n = read(), m = read();ll sum = 0;for(int i = 1; i <= n; i++) a[i] = read(), sum += a[i];int l = 0, r = sum / m;while(l < r) {
int mid = l + r + 1 >> 1;if(check(mid)) l = mid;else r = mid - 1;}printf("%d\n", l);
}int main()
{
int T = 1;T = read();for(int i = 1; i <= T; ++i) {
solve();}return 0;
}