E. Maximum Monogonosity

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     for (int i = 0; i <= n; i++) {
21         for (int j = 0; j <= m; j++) {
22             f[i][j] = -0x3f3f3f3f3f3f3f3f;
23         }
24         for (int j = 0; j < 4; j++) {
25             g[i][j] = -0x3f3f3f3f3f3f3f3f;
26         }
27     }
28     f[0][0] = 0;
29     for (int i = 0; i <= n; i++) {
30         for (int j = 0; j <= min(i, m); j++) {
31             int k = i - j;
32             if (i) {
33                 f[i][j] = f[i - 1][j];
34                 f[i][j] = max(f[i][j], a[i] - b[i] + g[k][0]);
35                 f[i][j] = max(f[i][j], a[i] + b[i] + g[k][1]);
36                 f[i][j] = max(f[i][j], -a[i] - b[i] + g[k][2]);
37                 f[i][j] = max(f[i][j], -a[i] + b[i] + g[k][3]);
38             }
39             g[k][0] = max(g[k][0], f[i][j] + a[i + 1] - b[i + 1]);
40             g[k][1] = max(g[k][1], f[i][j] - a[i + 1] - b[i + 1]);
41             g[k][2] = max(g[k][2], f[i][j] + a[i + 1] + b[i + 1]);
42             g[k][3] = max(g[k][3], f[i][j] - a[i + 1] + b[i + 1]);
43         }
44     }
45     printf("%lld\n", f[n][m]);
46 }
47 
48 int main() {
49     int t;
50     scanf("%d", &t);
51     while (t--) {
52         solve();
53     }
54     
55     return 0;
56 }

 

参考资料

  Codeforces Round #892 (Div. 2) Editorial:https://codeforces.com/blog/entry/119287

posted @ 2023-08-14 20:15  onlyblues  阅读(39)  评论(0编辑  收藏  举报
Web Analytics