【CF660F】Bear and Bowling 4
阿新 • • 發佈:2021-11-04
題目
題目連結:https://codeforces.com/problemset/problem/660/F
給一個長度為 \(n\) 的序列 \(a\),選一個區間 \([l,r]\) 使得 \(\sum^{r}_{i=l}(i-l+1)\times a_i\) 最大。
\(n\leq 2\times 10^5\)。
思路
記 \(f_i\) 為 \(a\) 的字首和,\(g_i=\sum^{i}_{j=1}j\times a_j\)。那麼
\[ans_j=\max_{0\leq i<j}(g_j-g_i-i\times (f_j-f_i)) \]維護一個上突殼,二分斜率即可。
時間複雜度 \(O(n\log n)\)
程式碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=200010; int n,top,q[N]; ll ans,f[N],g[N],X[N],Y[N]; double slope(int i,int j) { return 1.0*(Y[i]-Y[j])/(X[i]-X[j]); } int binary(double k) { int l=2,r=top,mid; while (l<=r) { mid=(l+r)>>1; if (slope(q[mid],q[mid-1])>=k) l=mid+1; else r=mid-1; } return q[l-1]; } int main() { scanf("%d",&n); for (int i=1,x;i<=n;i++) { scanf("%d",&x); f[i]=f[i-1]+x; g[i]=g[i-1]+1LL*x*i; X[i]=i; Y[i]=1LL*i*f[i]-g[i]; } q[++top]=0; for (int i=1;i<=n;i++) { int j=binary(f[i]); ans=max(ans,g[i]-g[j]-1LL*j*(f[i]-f[j])); while (top>1 && slope(q[top-1],q[top])<=slope(q[top],i)) top--; q[++top]=i; } cout<<ans; return 0; }