小A与最大子段和 斜率优化 + 二分 + 细节
Code:
#include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #define x(i) (1.0000*i) #define y(i) (1.0000*s2[i]*i-1.00000*s1[i]) #define maxn 300000 #define ll long long #define ldb double using namespace std; int tail,head,n; int q[maxn]; ll s1[maxn],s2[maxn],f[maxn]; ldb slope(int i,int j) { return (ldb)(1.0*y(i)-y(j))/(ldb)(1.0*x(i)-x(j)); } int main() { int i,j; ll ans=-1e18; // setIO("input"); scanf("%d",&n); for(i=1;i<=n;++i) { scanf("%lld",&s2[i]); s1[i]=s1[i-1]+s2[i]*i; s2[i]+=s2[i-1]; } head=tail=1; for(i=1;i<=n;++i) { int l=head,r=tail,re=0,mid=0; while(l<=r) { mid=(l+r)>>1; if(mid==tail) { re=tail; break; } if(slope(q[mid],q[mid+1])<=s2[i]) re=mid,r=mid-1; else l=mid+1; } f[i]=s1[i]-s1[q[re]]-(s2[i]-s2[q[re]])*q[re]; ans=max(ans,f[i]); while(head<tail&&slope(i,q[head-1])>slope(q[head],q[head-1])) --tail; q[++tail]=i; } printf("%lld\n",ans); return 0; }