cf578 C. Weakness and Poorness(三分、最大子段和)
题意:
子段的价值定义为子段和的绝对值。数组的价值定义为最大子段价值。
把给定整数组中的所有数减去一个实数x,最小化数组的价值。
\(n\le 2e5, |a_i|\le 1e4\)
思路:
数组的价值关于x是单峰下凸的。在 \([-1e4,1e4]\) 中三分x即可。线性求最大字段和是经典贪心了。
注意浮点数三分要限制次数而非eps!实测eps取1e-11会wa,取1e-12又会tle,实在难绷。次数的话,取100次或200次左右都行。
const signed N = 2e5 + 3;
int n, a[N];
db f(db x)
{
db m1 = 0, m2 = 0, s1 = 0, s2 = 0;
for(int i = 1; i <= n; i++)
s1=max(s1,0.0)+(db)a[i]-x, m1 = max(m1, s1),
s2=min(s2,0.0)+(db)a[i]-x, m2 = min(m2, s2);
return max(m1, -m2);
}
signed main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
db l = -1e4, r = 1e4;
int m = 100; while(m--)
{
db lm = l + (r - l) / 3;
db rm = r - (r - l) / 3;
if(f(lm) < f(rm)) r = rm;
else l = lm;
}
cout << fixed << setprecision(7) << f(l);
}