CodeForce-752E - Santa Claus and Tangerines【二分】
二分答案X,判断能否通过均分比X大的橘子,使得数量>=K。
对于给定x,均分A[i],能分得的种类数是
x * 2的t次方 <= A[i] 的最大的t
易知
求得t后,所分得的权值差只有可能为1,即分得一堆Z和一堆Z+1
有时候虽然Z没有分的必要,但是Z+1还有继续分的必要,所以对于(Z+1) == 2 *X的情况,我们需要特殊考虑。
代码如下。
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; long long a[1000333]; long long e[40]; long long n, k; bool check(long long x) { long long cnt = 0; for (int i = 1 ; i <= n; i++) { //均分比X小的。 if (a[i] < x) break; //求得分的次数 int pos = upper_bound(e, e + 33, a[i] / x) - e - 1; cnt += e[pos]; //如果分成e[pos]个正好变成e[pos]个X if (a[i] % e[pos] == 0) continue; //完全分成e[pos]份,部分还能继续分。 if ((a[i] / e[pos] + 1) / x == 2 ) cnt += (a[i] % e[pos]); } if (cnt >= k) return true; else return false; } inline bool cmp(long long & x, long long & y) { return x > y; } int main() { cin >> n >> k; long long sum = 0; for (int i = 1; i <= n; i++) { scanf("%I64d", & a[i]); sum += a[i]; } sort(a + 1, a + n + 1, cmp); if (sum < k) { cout << -1 << endl; return 0; } // 2 的 i 次方 e[0] = 1; for (int i = 1 ; i <= 33; i++) e[i] = e[i - 1] * 2LL; long long ans = 1; long long l = 1, r = sum / k; //二分 while (l <= r) { long long mid = (l + r) >> 1; if (check(mid)) { ans = mid; l = mid + 1; } else { r = mid - 1; } } cout << ans << endl; }