BZOJ1816
-
题目
-
分析
考虑二分。。
发现若二分最多组成套牌数目, [ 1 , r ] [1,r] [1,r] 可以组成, [ 1 , r − 1 ] [1,r - 1] [1,r−1] 也必然可以组成,显然满足单调性。
二分套牌数目,因为要组成 m i d mid mid 数目的套牌,所以 a [ i ] a[i] a[i] 的数目都不可能比 m i d mid mid 小,如果比 m i d mid mid 小那么就要使用 j o k e r joker joker ,使用 j o k e r joker joker 的数目是 m i d − a [ i ] mid - a[i] mid−a[i] ,因为每套牌只能使用一张 j o k e r joker joker ,所以能使用 j o k e r joker joker 的数目是 m i n ( m , m i d ) min(m,mid) min(m,mid) ,使用了 j o k e r joker joker 后,一定能在其他牌里面凑齐 n − 1 n-1 n−1个不是 j o k e r joker joker 的牌。
证明:
如 果 对 于 i , a [ i ] ≤ m i d 则 需 要 补 的 j o k e r 数 目 是 m i d − a [ i ] 若 其 它 n − 1 个 数 存 在 j , a [ j ] < m i d − a [ i ] , 这 表 明 没 有 办 法 凑 齐 不 是 j o k e r 的 牌 , 即 : a [ i ] + a [ j ] < m i d . 当 遍 历 到 j 时 , i , j 需 要 j o k e r 的 总 数 目 为 : m i d − a [ i ] + m i d − a [ j ] , 又 因 为 a [ j ] + a [ i ] < m i d 所 以 : m i d − a [ i ] + m i d − a [ j ] > m i d 此 时 : _ < 0 就 成 判 断 不 可 能 了 。 \begin{aligned} &\ 如果对于 i, a[i] \leq mid \\ &\ 则需要补的joker数目是mid - a[i] \quad 若其它n - 1个数存在j,a[j] < mid - a[i],这表明没有\\&办法凑齐不是 joker 的牌,即:a[i] + a[j] < mid.\\ &当遍历到 j 时,i,j需要joker 的总数目为:mid - a[i] + mid - a[j],又因为 a[j] + a[i] < mid \\ & 所以:mid - a[i] + mid - a[j] > mid\\ & 此时:\_ < 0 就成判断不可能了。 \end{aligned} 如果对于i,a[i]≤mid 则需要补的joker数目是mid−a[i]若其它n−1个数存在j,a[j]<mid−a[i],这表明没有办法凑齐不是joker的牌,即:a[i]+a[j]<mid.当遍历到j时,i,j需要joker的总数目为:mid−a[i]+mid−a[j],又因为a[j]+a[i]<mid所以:mid−a[i]+mid−a[j]>mid此时:_<0就成判断不可能了。
或者不嫌麻烦在 a [ i ] < m i d a[i] < mid a[i]<mid 判断一下, n n n 的范围太小了。。。 -
代码
int n, m; int a[55]; int solve(int mid) { int _ = min(m, mid); for (int i = 1; i <= n; i++) { if(a[i] < mid) { _ -= (mid - a[i]); if(_ < 0) return 0; } } return 1; } int main () { //freopen("input.in", "r", stdin); //freopen("test.out", "w", stdout); read(n); read(m); for (int i = 1; i <= n; i++) read(a[i]); int l = 0; int r = 0; for (int i = 1; i <= n; i++) { r = max(r, a[i]); } r += m + 1; while (l < r) { int mid = (l + r + 1) >> 1; if (solve(mid)) l = mid; else r = mid - 1; } cout << l << endl; return 0 ; }
-
题型
二分