Codeforces 460C —— Present(二分答案)
阿新 • • 發佈:2018-12-23
題意:給定N朵花的原先的高度,從左到右排列,最多澆水m天,每天只能澆一次,每次使得連續的w朵花的高度增長1,問最後最矮的花的高度最高是多少。
直接對答案進行二分,對於高度X的判定,從左往右遍歷花的高度,如果當前高度低於X,則用相應的天數澆水,如果天數不夠就說明不可行。
至於處理方面,目測寫個線段樹、樹狀陣列維護區間問題應該也可以,但也有比較簡便的方法。
用一個數組b,初始化全部為0,再用一個變數C,初值也為0,如果當前需要澆水p天,則C+=p,表明後面的花也會澆到,在b[i+w]的位置減去p,表示當前的澆水的影響到這裡結束,每訪問到一個位置就先用C+b[i],然後再判斷a[i]+C與x的大小關係。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n, m, w; int a[100010], b[100010]; bool ok(int x){ memset(b, 0, sizeof(b)); int k = m; int c = 0; int p; for(int i=0; i<n; i++){ c += b[i]; if(a[i]+c<x){ p = x-a[i]-c; if(p>k) return 0;//天數不足,不可行 k-=p; c+=p; b[(i+w)>=n?n:(i+w)]-=p; } } return 1; } int main(){ while(~scanf("%d %d %d", &n, &m, &w)){ int low, top; for(int i=0; i<n; i++){ scanf("%d", a+i); if(i){ low = min(low, a[i]); top = max(top, a[i]); } else{ low=top=a[i]; } } top+=m; int ans = low; while(low<=top){ int mid = (low+top)>>1; if(ok(mid)){ ans = max(ans, mid); low = mid+1; } else{ top = mid-1; } } printf("%d\n", ans); } return 0; }