由于要访问每个格子刚好一次,所以只可能是一种情况,先上上下下访问然后再一直向右到达N处然后返回访问另一行未访问的格子,所以通过枚举开始一直向右走的起始位置可以得到结果。
终于在standing里面找到了一份能看懂的代码...orzAllunlimited大佬
其中f[i]表示,以第一行的第i个格子为时间零点,从第一行的第i个格子一直往右然后回到第二行的第i个格子的时间。
g[i]表示,以第二行的第i个格子为时间零点,从第二行的第i个格子一直往右然后回到第一行的第i个格子的时间。
f[i],g[i]都是通过倒推得到.
h[i]表示以上上下下的方式访问完前2*i个格子所花费的时间。
所以最后结果就是在h[i] + (i & 1 ? g[i + 1] : f[i + 1]) + (i * 2)*sum[i + 1]中取最大值
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 300005
#define ll long long
using namespace std;
ll n, a[N], b[N], sum[N], f[N], g[N], h[N];
int main()
{
ll i, j, k, x, y, ans = 0;
scanf("%I64d", &n);
for (i = 1; i <= n; i++)scanf("%I64d", &a[i]);
for (i = 1; i <= n; i++)scanf("%I64d", &b[i]);
for (i = n; i >= 1; i--)sum[i] = sum[i + 1] + a[i] + b[i];
for (i = n; i >= 1; i--)
{
f[i] = b[i] * (2 * (n - i) + 1) + sum[i + 1] + f[i + 1];
g[i] = a[i] * (2 * (n - i) + 1) + sum[i + 1] + g[i + 1];
}
for (i = 1; i <= n; i++)
{
if (i & 1)h[i] = h[i - 1] + ((i - 1) * 2)*a[i] + ((i - 1) * 2 + 1)*b[i];
else h[i] = h[i - 1] + ((i - 1) * 2 + 1)*a[i] + ((i - 1) * 2)*b[i];
}
for (i = 0; i <= n; i++)
ans = max(ans, h[i] + (i & 1 ? g[i + 1] : f[i + 1]) + (i * 2)*sum[i + 1]);
printf("%I64d\n", ans);
}