Solution

对于任意一组我们可以使其中间的数与之构成一个等差数列,利用数形结合,使每个数的,这在几何学上就是一个凸壳。
问题转换为求一个凸壳并计算答案。

凸壳需要满足:
对于任意三个点,由于除法有精度误差,上式转换为乘法。


若不满足上述条件则点需要删除。

最后对维护之后的凸壳进行等差数列求和即可,需要注意的是第到第个端点重复计算,需要减去。

Code

#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod  = 1e9 + 7;
const ll N = 1e6 + 5;

int n;
ll a[N],b[N],top;
double ans;

bool check(int x,int y,int z){
    return (a[z]-a[x])*(y-x)-(a[y]-a[x])*(z-x)<0;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(10);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
        while(top>=2 && check(b[top-1], b[top], i)) top--;
        b[++top]=i;
    }
    for(int i=2;i<=top;i++) ans+=(a[b[i-1]]+a[b[i]])*(b[i]-b[i-1]+1)/2.0;
    for(int i=2;i<=top-1;i++) ans-=a[b[i]];
    cout<<ans<<'\n';
    return 0;
}