【Codeforces1519D】Maximum Sum of Product(数学)

题目大意:

给出两个长度为\(n(1\le n\le5000)\)的数列,对一个数列的子段进行至多一次翻转操作,求两数组同下标数之积的总和的最大值。


由数据范围可知本题时间复杂度需控制在\(\Theta(n^{2})\)以内。我们考虑先枚举翻转区间的中心,再从中心向两边扩展区间,同时用得到的结果来更新答案。

每次扩展时,我们将左右两边的数对答案的贡献进行累加,区间外的部分可以通过前缀和求得。

区间长度可能是奇数或偶数,需要对这两种情况进行分类讨论。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,a[5000+10],b[5000+10],abpre[5000+10],absuf[5000+10],ans;
int main(){
	cin >> n;
	for(ll i=1;i<=n;i++)cin >> a[i];
	for(ll i=1;i<=n;i++)cin >> b[i];
	for(ll i=1;i<=n;i++)abpre[i]=abpre[i-1]+a[i]*b[i];
	for(ll i=n;i>=1;i--)absuf[i]=absuf[i+1]+a[i]*b[i];
	ans=abpre[n];
	for(ll i=1;i<=n;i++){
		ll sum=a[i]*b[i];
		for(ll j=1;i-j>=1&&i+j<=n;j++){		//[i-j,i+j]
			sum+=a[i-j]*b[i+j]+a[i+j]*b[i-j];
			ans=max(sum+abpre[i-j-1]+absuf[i+j+1],ans);
		}
	}
	for(ll i=1;i<=n;i++){
		ll sum=0;
		for(ll j=1;i-j+1>=1&&i+j<=n;j++){	//[i-j+1,i+j]
			sum+=a[i-j+1]*b[i+j]+a[i+j]*b[i-j+1];
			ans=max(sum+abpre[i-j+1-1]+absuf[i+j+1],ans);
		}
	}
	cout << ans;
	return 0;
}
posted @ 2023-08-28 13:26  Alric  阅读(9)  评论(0编辑  收藏  举报