BZOJ 1816: [Cqoi2010]撲克牌 二分
阿新 • • 發佈:2018-11-27
Description
你有n種牌,第i種牌的數目為ci。另外有一種特殊的牌:joker,它的數目是m。你可以用每種牌各一張來組成一套牌,也可以用一張joker和除了某一種牌以外的其他牌各一張組成1套牌。比如,當n=3時,一共有4種合法的套牌:{1,2,3}, {J,2,3}, {1,J,3}, {1,2,J}。 給出n, m和ci,你的任務是組成儘量多的套牌。每張牌最多隻能用在一副套牌裡(可以有牌不使用)。
Input
第一行包含兩個整數n, m,即牌的種數和joker的個數。第二行包含n個整數ci,即每種牌的張數。
Output
輸出僅一個整數,即最多組成的套牌數目。
Sample Input
3 4
1 2 3
Sample Output
3
樣例解釋
輸入資料表明:一共有1個1,2個2,3個3,4個joker。最多可以組成三副套牌:{1,J,3}, {J,2,3}, {J,2,3},joker還剩一個,其餘牌全部用完。
資料範圍
50%的資料滿足:2 < = n < = 5, 0 < = m < = 10^ 6, 0< = ci < = 200
100%的資料滿足:2 < = n < = 50, 0 < = m, ci < = 500,000,000。
思路
這個題是二分答案。
然後判斷。我們二分出來的答案,看看滿不滿足條件。
看每堆的牌數還要加幾個 joker 牌才能到 我們二分的答案。
最後還要判斷是不是會出現有兩堆出現 joker。
#include<bits/stdc++.h>
using namespace std;
int a[100],n,m;
bool judge(int x){
int t = min(x,m);
for (int i = 0; i < n; i++){
if (a[i] < x) t -= (x - a[i]);
if (t < 0) return 0;
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for (int i = 0; i < n; i++)
scanf("%d",& a[i]);
int l = 0,r = 1e9,ans;
while(l <= r){
int mid = (l + r) >> 1;
if (judge(mid)) {
l = mid + 1;
ans = mid;
} else r = mid - 1;
}
printf("%d\n",ans);
return 0;
}