2019 ICPC沈阳 Flowers

    科技2022-07-11  104

    题意: 给定 n n n种花,第 i i i种有 a i a_i ai朵,一束花由 m m m朵互不相同种类的花组成,问最多可以组成多少束花。 数据范围: 1 ≤ n , m ≤ 3 × 1 0 5 , 1 ≤ a i ≤ 1 0 9 1\leq n,m\leq 3\times10^5,1\leq a_i\leq 10^9 1n,m3×105,1ai109

    题解: 二分答案,设当前答案为 x x x,判断答案是否合法,合法则真实答案至少为 x x x,否则真实答案至多为 x − 1 x-1 x1。判断条件是每种花取 c i = m i n ( x , a i ) c_i=min(x,a_i) ci=min(x,ai),最后判断 s u m ≥ ∑ c i sum \geq \sum c_i sumci是否成立即可。

    代码:

    #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; ll a[N]; int n, m; bool check(ll x) { ll sum = 0; for(int i = 1; i <= n; i++) sum += min(x, a[i]); return sum >= x * m; } void solve() { n = read(), m = read(); ll sum = 0; for(int i = 1; i <= n; i++) a[i] = readl(), sum += a[i]; ll l = 0, r = sum / m; while(l < r) { ll mid = l + r + 1 >> 1; if(check(mid)) l = mid; else r = mid - 1; } printf("%lld\n", l); } int main() { int T = 1; T = read(); for(int i = 1; i <= T; ++i) { solve(); } return 0; }
    Processed: 0.029, SQL: 8