ZOJ4062 Plants vs. Zombies(二分+貪心)
阿新 • • 發佈:2018-11-11
題目連結:傳送門
題目大意:
有n棵植物依次放在1-n,機器人從0出發澆水,每棵植物被澆水時di += ai,求澆m次水後min{di|1 ≤ i ≤ n}的最大值。(澆水時必須往左或往右走一步,落腳點為澆水點)
思路:
若已知答案mid(滑稽臉):可以貪心地從左到右澆水,反覆給di和di+1澆水,直到當前的di ≥ mid。。。O(n)。。。既然可以O(n)驗證答案,那就開心地二分掉了。
程式碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; constView Codeint MAX_N = 1e5 + 5; int N; ll M; ll a[MAX_N]; ll d[MAX_N]; bool judge(ll mid) { for (int i = 1; i <= N; i++) d[i] = 0; ll cnt = 0, jumped = 0; for (int i = 1; i <= N; i++) { if (d[i] >= mid) { jumped++; continue; } cnt += jumped; jumped = 0; ll mul = (mid-d[i])/a[i] + ((mid-d[i])%a[i] > 0); cnt += mul*2-1; d[i] += mul * a[i]; if (i+1 <= N) d[i+1] += (mul-1) * a[i+1]; } return cnt <= M; } int main() { int T; cin >> T; while (T--) { scanf("%d%lld", &N, &M); ll _max= 0; for (int i = 1; i <= N; i++) { scanf("%lld", a+i); _max = max(_max, a[i]); } ll l = 0, r = _max*M; ll ans = 0; while (l <= r) { ll mid = (l+r) >> 1; if (judge(mid)) { ans = max(ans, mid); l = mid+1; } else r = mid-1; } cout << ans << endl; } return 0; } /* 2 4 8 3 2 6 6 3 9 10 10 1 */