E. Maximum Monogonosity
You are given an array $a$ of length $n$ and an array $b$ of length $n$. The cost of a segment $[l, r]$, $1 \le l \le r \le n$, is defined as $|b_l - a_r| + |b_r - a_l|$.
Recall that two segments $[l_1, r_1]$, $1 \le l_1 \le r_1 \le n$, and $[l_2, r_2]$, $1 \le l_2 \le r_2 \le n$, are non-intersecting if one of the following conditions is satisfied: $r_1 < l_2$ or $r_2 < l_1$.
The length of a segment $[l, r]$, $1 \le l \le r \le n$, is defined as $r - l + 1$.
Find the maximum possible sum of costs of non-intersecting segments $[l_j, r_j]$, $1 \le l_j \le r_j \le n$, whose total length is equal to $k$.
Input
Each test consists of multiple test cases. The first line contains a single integer $t$ $(1 \le t \le 1000)$ — the number of sets of input data. The description of the test cases follows.
The first line of each test case contains two integers $n$ and $k$ ($1 \le k \le n \le 3000$) — the length of array $a$ and the total length of segments.
The second line of each test case contains $n$ integers $a_1, a_2, \ldots, a_n$ ($-10^9 \le a_i \le 10^9$) — the elements of array $a$.
The third line of each test case contains $n$ integers $b_1, b_2, \ldots, b_n$ ($-10^9 \le b_i \le 10^9$) — the elements of array $b$.
It is guaranteed that the sum of $n$ over all test case does not exceed $3000$.
Output
For each test case, output a single number — the maximum possible sum of costs of such segments.
Example
input
5 4 4 1 1 1 1 1 1 1 1 3 2 1 3 2 5 2 3 5 1 1 2 3 4 5 1 2 3 4 5 7 2 1 3 7 6 4 7 2 1 5 3 2 7 4 5 4 2 17 3 5 8 16 2 5 9
output
0 10 0 16 28
Note
In the first test case, the cost of any segment is $0$, so the total cost is $0$.
In the second test case, we can take the segment $[1, 1]$ with a cost of $8$ and the segment $[3, 3]$ with a cost of $2$ to get a total sum of $10$. It can be shown that this is the optimal solution.
In the third test case, we are only interested in segments of length $1$, and the cost of any such segment is $0$.
In the fourth test case, it can be shown that the optimal sum is $16$. For example, we can take the segments $[3, 3]$ and $[4, 4]$.
解题思路
最直接的dp做法还是很容易想到的,定义状态$f(i,j)$表示从前$i$个数中选出了总长度为$j$且互不相交的区间的所有方案中的最大值。根据以第$i$个数为右端点的区间长度进行状态划分,因此状态转移方程就是$$f(i,j) = \max\left\{ {f(i-1,j), \ \max_{1 \leq u \leq \min \left\{ {j,k} \right\}}\left\{ {f(i-u, j-u) + \left| {a_i-b_{i-u+1}} \right| + \left| {a_{i-u+1}-b_{i}} \right|} \right\}} \right\} \quad (j \leq i)$$
可以发现整个dp的时间复杂度是$O(n \cdot k^2)$,因此需要对状态表示或状态转移进行优化。当时想着推状态转移的式子然后找规律再结合数据结构来优化,结果发现好像不行,至少我没有做出来。然后看题解发现是对状态转移方程进行改写然后再优化,这个我肯定是想不到了。
对于$\left| a_l - b_r \right| + \left| a_r - b_l \right|$,其实是等价于$$\left| a_l - b_r \right| + \left| a_r - b_l \right| = \max\left\{ {b_l - a_r + b_r - a_l, \, b_l - a_r - b_r + a_l, \, -b_l + a_r + b_r - a_l, \, -b_l + a_r - b_r + a_l} \right\}$$
即我们只需对这$4$中组合求最大值即可,因此状态转移方程可以改写成如下形式:$$\begin{align*} f(i,j) &= \max\left\{ {f(i-1,j), \ \max_{1 \leq u \leq \min \left\{ {j,k} \right\}}\left\{ {f(i-u, j-u) + \left| {a_i-b_{i-u+1}} \right| + \left| {a_{i-u+1}-b_{i}} \right|} \right\}} \right\} \\\\ &= \max\Big\{ f(i-1,j), \\ & \qquad\quad \max_{1 \leq u \leq \min \left\{ {j,k} \right\}}\left\{ {f(i-u, j-u) - a_{i-u+1} + b_{i-u+1}} \right\} - a_i + b_i, \\ & \qquad\quad \max_{1 \leq u \leq \min \left\{ {j,k} \right\}}\left\{ {f(i-u, j-u) + a_{i-u+1} + b_{i-u+1}} \right\} - a_i - b_i, \\ & \qquad\quad \max_{1 \leq u \leq \min \left\{ {j,k} \right\}}\left\{ {f(i-u, j-u) - a_{i-u+1} - b_{i-u+1}} \right\} + a_i + b_i, \\ & \qquad\quad \max_{1 \leq u \leq \min \left\{ {j,k} \right\}}\left\{ {f(i-u, j-u) + a_{i-u+1} - b_{i-u+1}} \right\} + a_i - b_i \Big\} \\ \end{align*}$$
可以发现,状态$f(i,j)$总是通过$f(i-u,j-u)$转移得到,而$i-u - (j-u) = i-j$,即只要满足状态第一维减去第二维等于$i-j$,那么就可以转移到$f(i,j)$。形象点理解的话,可以把$n \times k$个状态看作是一个矩阵,$f(i,j)$表示矩阵中第$i$行第$j$列的元素,那么$f(i,j)$就可以从其所在的对角线之上的所有格子(状态)转移过来,如下图:
例如状态$f(7, 4)$就可以从$f(6,3)$,$f(5,2)$,$f(4,2)$转移过来。这有点类似于从某个前缀转移得到,不过在这里是斜线的前缀。一样的,我们可以用$i-j$来代表某条斜线,然后分别维护每条斜线关于$f(i,j)-a_{i+1}+b_{i+1}$,$f(i,j)+a_{i+1}+b_{i+1}$,$f(i,j)-a_{i+1}-b_{i+1}$,$f(i,j)+a_{i+1}-b_{i+1}$的前缀最大值,这样在状态转移时就可以降到$O(1)$。
AC代码如下,时间复杂度为$O(n \cdot k)$:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 3010; 7 8 int a[N], b[N]; 9 LL f[N][N], g[N][4]; 10 11 void solve() { 12 int n, m; 13 scanf("%d %d", &n, &m); 14 for (int i = 1; i <= n; i++) { 15 scanf("%d", a + i); 16 } 17 for (int i = 1; i <= n; i++) { 18 scanf("%d", b + i); 19 } 20 memset(f, -0x3f, (n + 10) * (m + 10) << 3); 21 memset(g, -0x3f, (n + 10) * (m + 10) << 3); 22 f[0][0] = 0; 23 for (int i = 0; i <= n; i++) { 24 for (int j = 0; j <= min(i, m); j++) { 25 int k = i - j; 26 if (i) { 27 f[i][j] = f[i - 1][j]; 28 f[i][j] = max(f[i][j], a[i] - b[i] + g[k][0]); 29 f[i][j] = max(f[i][j], a[i] + b[i] + g[k][1]); 30 f[i][j] = max(f[i][j], -a[i] - b[i] + g[k][2]); 31 f[i][j] = max(f[i][j], -a[i] + b[i] + g[k][3]); 32 } 33 g[k][0] = max(g[k][0], f[i][j] + a[i + 1] - b[i + 1]); 34 g[k][1] = max(g[k][1], f[i][j] - a[i + 1] - b[i + 1]); 35 g[k][2] = max(g[k][2], f[i][j] + a[i + 1] + b[i + 1]); 36 g[k][3] = max(g[k][3], f[i][j] - a[i + 1] + b[i + 1]); 37 } 38 } 39 printf("%lld\n", f[n][m]); 40 } 41 42 int main() { 43 int t; 44 scanf("%d", &t); 45 while (t--) { 46 solve(); 47 } 48 49 return 0; 50 }
解题思路
Codeforces Round #892 (Div. 2) Editorial:Codeforces Round #892 (Div. 2) Editorial - Codeforces
标签:le,max,Monogonosity,Maximum,leq,right,test,left From: https://www.cnblogs.com/onlyblues/p/17629372.html