CF1519D 题解

思路

我们设 dpi,jdp_{i,j} 表示翻转 aiaja_i\sim a_j 后和增加了几。ai,ai+1,ai+2,,aj2,aj1,aja_i,a_{i+1},a_{i+2},\dots,a_{j-2},a_{j-1},a_j 反转后变成了 aj,aj1,aj2,,ai+2,ai+1,aia_j,a_{j-1},a_{j-2},\dots,a_{i+2},a_{i+1},a_i,而 ai+1,ai+2,,aj2,aj1a_{i+1},a_{i+2},\dots,a_{j-2},a_{j-1} 翻转后成为了 aj1,aj2,,ai+2,ai+1a_{j-1},a_{j-2},\dots,a_{i+2},a_{i+1},我们发现,其中 ai+1aj1a_{i+1}\sim a_{j-1} 翻转前后都是重复的,所以不用重复算那一段,dpi,jdp_{i,j}dpi+1,j1dp_{i+1,j-1} 转移过来,dpi,j=dpi+1,j1+ai×bj+bi×biai×biaj×bjdp_{i,j}=dp_{i+1,j-1}+a_i\times b_j+b_i\times b_i-a_i\times b_i-a_j\times b_j。然后区间 dp 就从长度入手,先枚举长度再枚举左右端点转移即可。

代码

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
int n;
ll dp[5005][5005], a[5005], b[5005], sum, maxx;
int main () {
	ios::sync_with_stdio (0);
	cin.tie (0);
	cout.tie (0);
	cin >> n;
	for (int i = 1; i <= n; ++ i)
		cin >> a[i];
	for (int i = 1; i <= n; ++ i)
		cin >> b[i], sum += a[i] * b[i];
	for (int len = 2; len <= n; ++ len)
		for (int l = 1, r = len; r <= n; ++ l, ++ r)
			maxx = max (maxx, dp[l][r] = dp[l + 1][r - 1] + a[l] * b[r] - a[l] * b[l] + a[r] * b[l] - a[r] * b[r]);
	cout << maxx + sum;
	return 0;
}
posted @ 2024-05-07 15:08  Vitamin_B  阅读(7)  评论(0)    收藏  举报  来源