题意:确定一个x使序列a1-x,a2-x,...,an-x的weakness最小,输出最小weakness。(weakness是连续子序列的和的绝对值的最小值)
解法:以前对二分的理解就是二分答案,上下界分别在目标解的两侧,其中一个满足一个不满足。这个题值得自己反思了。
正解二分X,目标情况的X值应该是这段序列的连续子序列的最大值和最小值的和逼近0。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200005;
const double eps = 1e-12;
const double inf = 1e10;
int n,a[maxn];double dp[2][maxn];
int main(){
int i,j;
scanf("%d",&n);
for(i = 0;i < n;i++) scanf("%d",&a[i]);
double t1,t2,mid,lb = -20000,rb = 20000;
while(rb-lb>eps){
mid = (lb+rb)/2;
for(i = 0;i < n;i++) dp[0][i] = t1 = -inf,dp[1][i] = t2 = inf;
for(i = 0;i < n;i++){
dp[0][i] = i?max(a[i]-mid,dp[0][i-1]+a[i]-mid):a[i]-mid;
dp[1][i] = i?min(a[i]-mid,dp[1][i-1]+a[i]-mid):a[i]-mid;
t1 = max(t1,dp[0][i]);t2 = min(t2,dp[1][i]);
}
//printf("%.6f %.6f %.6f\n",t1,t2,mid);
if(t1+t2>0) lb = mid;
else rb = mid;
}
printf("%.9f\n",t1);
return 0;
}