AtCoder Beginner Contest 063 - D - Widespread (二分答案)
Time Limit: 2 sec / Memory Limit: 256 MB
Score : 400 points
Problem Statement
You are going out for a walk, when you suddenly encounter NN monsters. Each monster has a parameter called health, and the health of the ii-th monster is hihi at the moment of encounter. A monster will vanish immediately when its health drops to 00 or below.
Fortunately, you are a skilled magician, capable of causing explosions that damage monsters. In one explosion, you can damage monsters as follows:
- Select an alive monster, and cause an explosion centered at that monster. The health of the monster at the center of the explosion will decrease by AA, and the health of each of the other monsters will decrease by BB. Here, AA and BB are predetermined parameters, and A>BA>B holds.
At least how many explosions do you need to cause in order to vanish all the monsters?
Constraints
- All input values are integers.
- 1≤N≤1051≤N≤105
- 1≤B<A≤1091≤B<A≤109
- 1≤hi≤109
Input
Input is given from Standard Input in the following format:
NN AA BB
h1h1
h2h2
::
hNhN
Output
Print the minimum number of explosions that needs to be caused in order to vanish all the monsters.
Sample Input 1 Copy
Copy
4 5 3
8
7
4
2
Sample Output 1 Copy
Copy
2
You can vanish all the monsters in two explosion, as follows:
- First, cause an explosion centered at the monster with 88 health. The healths of the four monsters become 33, 44, 11 and −1−1, respectively, and the last monster vanishes.
- Second, cause an explosion centered at the monster with 44 health remaining. The healths of the three remaining monsters become 00, −1−1 and −2−2, respectively, and all the monsters are now vanished.
Sample Input 2 Copy
Copy
2 10 4
20
20
Sample Output 2 Copy
Copy
4
You need to cause two explosions centered at each monster, for a total of four.
题意:
你面对n个怪兽,第i个怪兽有h[i]健康值,你每一次攻击可以选择一个还活着的怪兽,然后使其健康值下降A,其他的怪兽的健康值下降B。当一个怪兽的健康值小于等于0时,这个怪兽就会消失。
现在问你最少需要多少次攻击可以使所有的怪兽都消失。
思路:
设函数F(x)代表攻击x次,最多可以消灭怪兽的数量。
容易知道该函数是一个单调不下降的函数。
于是我们可以二分答案ans,二分过程中去检测攻击ans次是否可以消灭所有怪兽。
距离检测过程为:
将所有怪兽健康值h[i]减去 ans*b, 减去后的h[i]仍大于0的 再减去\(cnt_i= \lceil \frac{h[i]}{(A-B)} \rceil\)
(注意h[i] 减去了ans*b后的)
然后返回\(ans>=\sum_{i=1}^n cnt_i\) 即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n;
ll h[maxn];
ll b, a;
bool check(ll x)
{
ll res = x;
repd(i, 1, n)
{
ll temp = h[i] - x * b;
if (temp > 0)
{
ll need = temp / (a - b);
if (temp % (a - b) != 0)
{
need++;
}
res -= need;
if (res < 0)
{
break;
}
}
}
return res >= 0;
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
n = readint();
a = readll();
b = readll();
repd(i, 1, n)
{
h[i] = readll();
}
ll l = 1ll;
ll r = inf;
ll mid;
ll ans;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid))
{
ans = mid;
r = mid - 1;
} else
{
l = mid + 1;
}
}
printf("%lld\n", ans );
return 0;
}