把题目给出的式子化简一下
得到i-->j的收益等于=1/2(bi(bj/aj)-bj*(bi/ai))
发现是一个f(x)g(y)-f(y)g(x)的形式
因此,这个收益等价于(bi,bi/ai),(bj,bj/aj),(0,0)三点围成的有向三角形的面积
最大的收益显然等价于这n个点的凸包的面积
#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define N 220000
#define eps 1e-7
#define inf 1e9+7
#define ll long long
using namespace std;
inline int read()
{
char ch=0;
int x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*flag;
}
int dcmp(double x)
{
if(fabs(x)<=eps)return 0;
return x>0?+1:-1;
}
struct Point
{
double x,y;
}p[N];
typedef Point Vector;
Vector operator+(Vector a,Vector b){return (Vector){a.x+b.x,a.y+b.y};}
Vector operator-(Vector a,Vector b){return (Vector){a.x-b.x,a.y-b.y};}
Vector operator*(Vector a,double k){return (Vector){a.x*k,a.y*k};}
Vector operator/(Vector a,double k){return (Vector){a.x/k,a.y/k};}
double Dot(Vector a,Vector b)
{
return a.x*b.x+a.y*b.y;
}
double Cross(Vector a,Vector b)
{
return a.x*b.y-a.y*b.x;
}
bool cmp(Point a,Point b)
{
if(a.x!=b.x)return a.x<b.x;
else return a.y<b.y;
}
struct Monotonous_Queue
{
int L,R;
Point Q[N];
void clear()
{
L=1;R=0;
memset(Q,0,sizeof(Q));
}
void push(Point o,int flag)
{
while(L<=R && (L!=R&&dcmp(Cross(o-Q[R-1],Q[R]-Q[R-1])*flag)<=0))R--;
Q[++R]=o;
}
double query()
{
double ans=0;
for(int i=L;i<R;i++)ans+=0.5*fabs(Cross(Q[i],Q[i+1]));
return ans;
}
}q;
int a[N],b[N];
int main()
{
int n,i;
double ans=0;
n=read();
for(i=1;i<=n;i++)a[i]=read(),b[i]=b[i-1]+a[i];
for(i=1;i<=n;i++)p[i]=(Point){(double)b[i],(double)b[i]/(double)a[i]};
sort(p+1,p+n+1,cmp);
q.clear();
for(i=1;i<=n;i++)q.push(p[i],+1);
ans+=q.query();
q.clear();
for(i=1;i<=n;i++)q.push(p[i],-1);
ans+=q.query();
printf("%.5lf",ans);
return 0;
}