1. 程式人生 > 其它 >【CF660F】Bear and Bowling 4

【CF660F】Bear and Bowling 4

題目

題目連結: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;
}