Loading

Educational Codeforces Round 108 (Rated for Div. 2) D. Maximum Sum of Products(对角线前缀和/区间DP/好题)

You are given two integer arrays a and b of length n.

You can reverse at most one subarray (continuous subsegment) of the array 𝑎a.

Your task is to reverse such a subarray that the sum \(\Sigma_{i = 1}^na_i\times b_i\) is maximized.

Input

The first line contains one integer n (1≤n≤5000).

The second line contains 𝑛n integers a1,a2,…,an (1≤ai≤10^7).

The third line contains 𝑛n integers b1,b2,…,bn (1≤bi≤10^7).

Output

Print single integer — maximum possible sum after reversing at most one subarray (continuous subsegment) of 𝑎a.

Examples

input

Copy

5
2 3 2 1 3
1 3 2 4 2

output

Copy

29

input

Copy

2
13 37
2 4

output

Copy

174

input

Copy

6
1 8 7 6 3 6
5 9 6 8 8 6

output

Copy

235

很容易就想到可以枚举反转的左右端点,反转区间两边的乘积和可以通过前缀和计算,但是中间的反转部分如果O(N)进行求解的话显然会T。因此考虑如何处理。通过观察发现,如果设\(mtx[i][j] = a[i]\times b[j]\),同时设反转的左右端点分别为l和r, 那么反转序列的乘积和为\(mtx[l][r] + mtx[l + 1][r - 1] + ... + mtx[r][l]\),放到矩阵里看会发现这个和反对角线是平行的,可以和处理普通的前缀和一样预处理得到,这样我们的计算反转区间值就能优化到O(1)了。对角线前缀和计算可以自行百度QAQ

同校大佬说了一个区间DP的做法,\(dp[i][j] = dp[i + 1][j - 1] + a[i]\times b[j] + a[j]\times b[i]\)也很巧妙。

#include <bits/stdc++.h>
using namespace std;
long long n, a[5005], b[5005], p[5005], sum[5005], ans = 0, sum1[5005][5005];//反对角线前缀和
int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i <= n; i++) cin >> b[i];
	sum[0] = 0;
	for(int i = 1; i <= n; i++) {
		p[i] = a[i] * b[i];
		sum[i] = sum[i - 1] + p[i];
	}
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			sum1[i][j] = sum1[i-1][j+1] + a[i] * b[j];
		}
	}
	for(int i = 1; i <= n; i++) { 
		for(int j = i; j <= n; j++) {
			int l = i, r = j;
			long long tmp = sum[l - 1] + sum[n] - sum[r];
			tmp += sum1[r][l]-sum1[l - 1][r + 1];
			ans = max(ans, tmp);
		}
	}
	cout << ans;
	return 0;
}
posted @ 2021-04-30 10:52  脂环  阅读(67)  评论(0编辑  收藏  举报