网址链接:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P0
Weakness and Poorness
You are given a sequence of n integers a1, a2, ..., an.
Determine a real number x such that the weakness of the sequence a1 - x, a2 - x, ..., an - x is as small as possible.
The weakness of a sequence is defined as the maximum value of the poorness over all segments (contiguous subsequences) of a sequence.
The poorness of a segment is defined as the absolute value of sum of the elements of segment.
给出一个n个整数a1,a2,...,an的序列。
求实数x使得新序列a1-x,a2-x,...,an-x的脆弱度尽可能小。
序列的脆弱度定义为序列的所有片段(连续子序列)上的不良性的最大值。
子序列的不良度被定义为子序列的元素的和的绝对值。
The first line contains one integer n (1 ≤ n ≤ 200 000), the length of a sequence.
The second line contains n integers a1, a2, ..., an (|ai| ≤ 10 000).
Output a real number denoting the minimum possible weakness of a1 - x, a2 - x, ..., an - x. Your answer will be considered correct if its relative or absolute error doesn't exceed 10 - 6.
3 1 2 3
1.000000000000000
4 1 2 3 4
2.000000000000000
10 1 10 2 9 3 8 4 7 5 6
4.500000000000000
Note For the first case, the optimal value of x is 2 so the sequence becomes - 1, 0, 1 and the max poorness occurs at the segment "-1" or segment "1". The poorness value (answer) equals to 1 in this case. For the second sample the optimal value of x is 2.5 so the sequence becomes - 1.5, - 0.5, 0.5, 1.5 and the max poorness occurs on segment "-1.5 -0.5" or "0.5 1.5". The poorness value (answer) equals to 2 in this case.
思路:
题目的专有名词再加上题意的模棱两可可能会让一些人蒙蔽。。大意就是:给出一个数组a,计算出新数组a[1]-x,a[2]-x,a[3]-x……的连续子序列元素的和(也就是区间和)的绝对值的最大值。而因为x值得不同,这个绝对值也会不同,这里我们要的最终结果就是:所有可能的绝对值的最小值!
连续子序列元素和的绝对值的最大值,根据上周作业的前缀和知识,我们很容易就能知道用max(sum[j])-min(sum[i])求得。
至于x的值,我们可以利用三分法来确定。三分法可用于求有数学函数关系的最小值问题。【算法讲解】三分法: http://www.cnblogs.com/syiml/p/3675214.html
/*
*区间和函数
*/
double f(double x)
{
int i;
double sum[200005]={0},max=0,min=0;//令max=min=sum[0]=0.
for(i=1;i<=n;i++)
{
sum[i]=sum[i-1]+a[i-1]-x;
if(max<sum[i])max=sum[i];
if(min>sum[i])min=sum[i];
}
return max-min;
}
/*
*三分法
*/
double l=-1e9,m,mm,r=1e9;
for(i=0;i<200;i++)//因为这里输出答案精度精确到15位,用固定次数循环比较方便。。100精度还不行,200亲测足矣!
{
m=l+(r-l)/3;//m,mm三等分。也可以m=(l+r)/2;
mm=r-(r-l)/3;//也可以mm=(m+r)/2;
if(f(m)<f(mm))r=mm;
else
l=m;
}