题目
一副扑克牌有
n
n
n张普通牌加一张特殊牌
现在
n
n
n种牌各有
a
1
,
a
2
,
…
,
a
n
a1,a2,…,an
a1,a2,…,an张,还有
b
b
b 张特殊牌
一副牌可以由n种普通牌各一张组成,也可以由n−1种普通牌各一张再加一张特殊牌组成
输出最多能整理出的牌的副数。
输入
第一行给出
n
n
n和
b
b
b。
第二行给出
a
1
,
a
2
,
…
,
a
n
a1,a2,…,an
a1,a2,…,an。
输出
输出最多能整理出的牌的副数。
数据
对于
20
20
20%的数据,
1
≤
n
≤
100
1≤n≤100
1≤n≤100,牌的数量小于
100
100
100。
对于
40
40
40%的数据,
1
≤
n
≤
3000
1≤n≤3000
1≤n≤3000。
对于
100
100
100%的数据,
1
≤
n
≤
1000000
1≤n≤1000000
1≤n≤1000000,牌的数量
≤
106
≤106
≤106。
时间限制:
1000
1000
1000
m
s
ms
ms
内存限制:
262144
K
B
262144 KB
262144KB
样例
input
5 5
5 5 5 5 5
output
6
思路
将扑克牌按照牌数排列(黄色区域)
很容易发现,我们只要将数量最少的牌用特殊牌代替,即可最大化地凑出一副牌。
观察问题,每一副牌最多只能用一张特殊牌,即
n
n
n副牌可以使用
n
n
n张特殊牌。
问题转换:长度为
n
n
n 的矩形高为
h
h
h,绿色格数为
a
a
a,求使得
a
<
=
h
a<=h
a<=h 的
h
h
h 的最大值
代码
#include<bits/stdc++.h>
using namespace std;
int n, b, ans, sum;
priority_queue< int, vector<int>, greater<int> > q;
int main() {
scanf("%d%d", &n, &b);
for(int i = 1, a; i <= n; i++) scanf("%d", &a), q.push(a);
ans = sum = q.top();
while(1) {
for(int i = 1; i <= sum && b; i++, b--) { int d = q.top();q.pop();q.push(d+1);}
//选择数量最少的牌,用一张特殊牌补上
int c = q.top();//目前最高可以到达的牌数
if(ans == c) break;//如果与上一轮得出答案相同,则最高牌数已求得
sum = c-ans;//sum记录还可以放的绿色格格数
ans = c;//更新答案
}
printf("%d\n", ans);
return 0;
}