CF460C Present (二分 + 差分数列)
Codeforces Round #262 (Div. 2) C
C. Present
time limit per test
2 secondsmemory limit per test
256 megabytesinput
standard inputoutput
standard outputLittle beaver is a beginner programmer, so informatics is his favorite subject. Soon his informatics teacher is going to have a birthday and the beaver has decided to prepare a present for her. He planted n flowers in a row on his windowsill and started waiting for them to grow. However, after some time the beaver noticed that the flowers stopped growing. The beaver thinks it is bad manners to present little flowers. So he decided to come up with some solutions. There are m days left to the birthday. The height of the i-th flower (assume that the flowers in the row are numbered from 1 to n from left to right) is equal to ai at the moment. At each of the remaining m days the beaver can take a special watering and water w contiguous flowers (he can do that only once at a day). At that each watered flower grows by one height unit on that day. The beaver wants the height of the smallest flower be as large as possible in the end. What maximum height of the smallest flower can he get? Input
The first line contains space-separated integers n, m and w (1 ≤ w ≤ n ≤ 105; 1 ≤ m ≤ 105). The second line contains space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 109). Output
Print a single integer — the maximum final height of the smallest flower. Sample test(s)
Input
6 2 3 Output
2 Input
2 5 1 Output
9 Note
In the first sample beaver can water the last 3 flowers at the first day. On the next day he may not to water flowers at all. In the end he will get the following heights: [2, 2, 2, 3, 2, 2]. The smallest flower has height equal to 2. It's impossible to get height 3 in this test. |
题意:给出一排花的碉值,共有n盆,初始碉值为a1,a2,...,an。每天可以增加连续的w盆花的碉值1点,进行m天,求碉值最低的花的碉值最大值。
题解:二分答案,用差分数列O(n)判断是否可行。
二分答案,设当前答案为x,也就是碉值最低的话的碉值最大值为x。
从头到尾观察花,若a[i]<x,则对a[i]开头的w盆花怒浇(x-a[i])天,让其碉值达到x。让所有的a[i]都>=x。若怒浇的天数和小于等于m,则可行。
而这个怒浇操作可以用差分队列实现,差分数列介绍在这里有:http://www.cnblogs.com/yuiffy/p/3923018.html
因为差分数列b[i]=a[i]-a[i-1],则当前点的值为now,下一个点的值就为now+b[i+1]。差分数列的L到R全加D操作: b[L]+=x; b[R+1]-=x;(注意这题R可能会怒超边界,记得特殊处理一下或者数组开大点)
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) prllf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 #define mp make_pair 26 #define pb push_back 27 vector<int>v; 28 int n,m,w; 29 int a[111111]; 30 int b[111111]; 31 32 void update(int L, int R, int x){ 33 b[L]+=x; 34 if(R+1<n) b[R+1]-=x; 35 } 36 37 bool check(int x){ 38 int i,j; 39 for(i=1;i<n;i++){ 40 b[i]=a[i]-a[i-1]; 41 } 42 int anow=a[0]; 43 int y=0; 44 for(i=0;i<n;i++){ 45 if(anow<x){ 46 update(i,i+w-1,x-anow); 47 y+=x-anow; 48 if(y>m)break; 49 anow=x; 50 } 51 anow+=b[i+1]; 52 } 53 if(y>m)return 0; 54 else return 1; 55 } 56 57 int main(){ 58 int i,j,k,mi; 59 scanf("%d%d%d",&n,&m,&w); 60 mi=1e9+7; 61 REP(i,n){ 62 scanf("%d",&a[i]); 63 mi=min(a[i],mi); 64 } 65 int l,r,mid; 66 l=mi;r=mi+m; 67 while(l<=r){ 68 mid=(r-l)/2+l; 69 if(check(mid))l=mid+1; 70 else r=mid-1; 71 } 72 printf("%d\n",r); 73 return 0; 74 }