储水
整体思路:二分答案
这个题目一眼二分,然后我就写了一个这个
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[1000001];
bool check(int x){
for(int i=2;i<=n;i++){
if(a[i]+x<a[i-1]-x) return 0;
}
return 1;
}
signed main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int l=-1,r=1e10+1;
while(l+1<r){
int m=l+r>>1ll;
if(check(m)) r=m;
else l=m;
}
cout<<r<<endl;
}
大概就是说,我们去判断m作为答案可不可以。不难发现,如果前一个数最小的可能值要比当前这个数的最小可能值要大,那么这个答案是不行的,return 0。否则如果都ok,那就return 1。
提交了,获得二十分的好成绩
为什么会这样?
看一下下面这个图片

这解释了刚刚的为什么不对
所以我们因该贪心一下,记录一个num,就是当前的值,接下来的值不能比它小
所以初始化num=\(a_1-x\)(x表示当前正在检查的答案)
然后,假设当前遍历到了\(i\)这个数。如果\(a_i+x≥num\),说明合法,更新num,\(num=max(num,a_i-x)\)
否则,return 0。
如果所有的都合法,return 1。
结束了……
代码如下
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[1000001];
bool check(int x){
int num=a[1]-x;
for(int i=1;i<=n;i++){
if(a[i]+x>=num) num=max(num,a[i]-x);
else return 0;
}
return 1;
}
signed main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int l=-1,r=1e10+1;
while(l+1<r){
int m=l+r>>1;
if(check(m)) r=m;
else l=m;
}
cout<<r<<endl;
}

浙公网安备 33010602011771号