题目链接:https://codeforces.com/contest/1859/problem/E
题意:
有长度为n的a和b俩个序列,定义f【l,r】 = abs(a【l】-b【r】) + abs(b【l】-a【r】);
给正整数k,求 不相交 的 区间 且 所有 区间的长度 的 和 为 k 的 最大值 是多少?
分析:
这里借鉴一个佬的思路:
首先考虑比较正常的dp,dp【i】【j】 为前 i 的长度里 有 j 个 长度被选中的最大价值,那么转移方程是:
直接转移的话,时间复杂度是 O(n*k^2) ,显然是过不了,考虑优化;
看出原式是有绝对值的,考虑把绝对值展开:
归纳总结一下:
那么可以看出,我们可以用4个一维dp来记录一下左边括号内的数,那么时间复杂度可以优化到 :O(n*k);
代码:
#include<bits/stdc++.h> #define int long long const int N = 3e3 + 3; int dp[N][N], f[4][N]; signed main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int T; std::cin >> T; while (T--) { int n, m; std::cin >> n >> m; std::memset(f, 0x80, sizeof f); std::vector<int> a(n + 1, 0), b(n + 1, 0); for (int i = 1; i <= n; ++i)std::cin >> a[i]; for (int i = 1; i <= n; ++i)std::cin >> b[i]; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m && j <= i; ++j) { dp[i][j] = dp[i - 1][j]; f[0][i - j] = std::max(f[0][i - j], dp[i - 1][j - 1] - a[i] - b[i]); f[1][i - j] = std::max(f[1][i - j], dp[i - 1][j - 1] + a[i] - b[i]); f[2][i - j] = std::max(f[2][i - j], dp[i - 1][j - 1] - a[i] + b[i]); f[3][i - j] = std::max(f[3][i - j], dp[i - 1][j - 1] + a[i] + b[i]); dp[i][j] = std::max(dp[i][j], f[0][i - j] + a[i] + b[i]); dp[i][j] = std::max(dp[i][j], f[1][i - j] + a[i] - b[i]); dp[i][j] = std::max(dp[i][j], f[2][i - j] - a[i] + b[i]); dp[i][j] = std::max(dp[i][j], f[3][i - j] - a[i] - b[i]); } std::cout << dp[n][m] << "\n"; } return 0; }
感觉这题纯dp,先有朴素想法,然后把绝对值展开,再来个简单dp,结合一下就可以了:)
- Monogonosity Codeforces Maximum 数学 动态monogonosity codeforces maximum数学 monogonosity maximum educational codeforces数学 动态 codeforces maximum prefix 1810g codeforces distance minimum maximum codeforces strength maximum round codeforces subarray maximum 1796d educational codeforces思维 数学 专场codeforces数学round monogonosity