【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;
}