持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情
【Codeforces】Educational Codeforces Round 108D. Maximum Sum of Products | 双指针
题目链接
题目
题目大意
给定两个长度为 的正整数数组 和 。定义操作为选择两个下标 ,把 数组的子串 翻转,即把 数组变为
操作完成后,更新 数组的下标,使其下标仍为 递增排列。
求最多进行一次操作后,最大的能取得的 。
思路
是 5000,时间复杂度 的做法是可以接受的。
首先我们可以预处理出不进行操作的 和 对应位置相乘得到的积的前缀和。这样对于一个翻转的区间 ,我们就可以 求出未翻转部分的答案是 。
如果我们直接枚举 数组中翻转的区间,每次进行区间翻转后,两数组对应相乘的关系都会发生巨大的改变,我们将不得不重新计算。
为了减小时间复杂度,我们需要考虑怎样最大程度的利用我们求出来的值。如果我们先枚举翻转的对称轴,再枚举翻转的半径,则半径增大 ,对应相乘的关系仅有两端的元素会发生改变,可以 求出变化量。考虑到翻转的区间可能是奇数也可能是偶数,我们枚举对称轴时可以使用两个变量。
代码
#include <stdio.h>
#include <algorithm>
using namespace std;
using LL=long long;
const int N=5001;
const LL mod=998244353;
LL a[N],b[N],ans=0,sum[N];
int n;
void solve()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
for (int i=1;i<=n;++i)
{
scanf("%d",&b[i]);
ans+=a[i]*b[i];
sum[i]=sum[i-1]+a[i]*b[i];
}
LL qwq=0;
for (int lm=1,rm=1;rm<=n;)
{
if (lm==rm) qwq=a[lm]*b[rm];
else qwq=0;
for (int r=(lm==rm);lm-r>=1&&rm+r<=n;r++)
{
qwq+=a[lm-r]*b[rm+r]+a[rm+r]*b[lm-r];
ans=max(ans,qwq+sum[lm-r-1]+sum[n]-sum[rm+r]);
}
if (lm==rm) rm++;
else lm++;
}
printf("%lld\n",ans);
}
int main()
{
solve();
return 0;
}