比赛链接
C. 交换
题目大意
给定一个长度为 n n n 的数组 a a a。一开始你有一个总和 s = 0 s = 0 s=0。
现在你需要做 n n n 次操作,第 i i i 次操作的流程如下( 1 ⩽ i ⩽ n 1 \leqslant i \leqslant n 1⩽i⩽n):
- 选择一个下标 p ∈ [ 1 , n ) p \in [1, n) p∈[1,n),然后交换 a [ p ] , a [ p + 1 ] a[p], \ a[p + 1] a[p], a[p+1](如果你不想选,这一小步可以跳过);
- s : = s + a [ i ] s := s + a[i] s:=s+a[i];
求 n n n 次操作结束后你能获得的最大的 s s s。
数据范围
- 2 ⩽ n ⩽ 500 2 \leqslant n \leqslant 500 2⩽n⩽500;
- 1 ⩽ a i ⩽ 1 0 6 1 \leqslant a_i \leqslant 10^6 1⩽ai⩽106;
Solution
我们观察这个数据范围,一眼 O ( n 3 ) O(n^3) O(n3) 的解法,而且大概率 d p dp dp。只不过有可能是 O ( n 2 ) O(n^2) O(n2) 的状态, O ( n ) O(n) O(n) 的转移;还有可能是 O ( n 3 ) O(n^3) O(n3) 的状态,以及需要优化成 O ( 1 ) O(1) O(1) 的转移。
首先,我们的状态需要操作次数 i i i,因为每个操作次数要加的 a [ i ] a[i] a[i] 不一样。其次,我们还要交换次数 j j j,因为每次操作可以不选下标 p p p 进行交换。最后,我们还要知道交换后 a [ i ] a[i] a[i] 变成了什么,即 a [ i ] : = a [ k ] a[i] := a[k] a[i]:=a[k],我们仅需记录这个 k k k。
这样就确定了我们的状态是 O ( n 3 ) O(n^3) O(n3) 的,因此我们一定需要 O ( 1 ) O(1) O(1) 的优化转移。
设 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k] 表示进行了 i i i 次操作,已经做了 j j j 次交换,将 a [ i ] : = a [ k ] a[i] := a[k] a[i]:=a[k] 能得到的最大 s s s。
状态转移:
- d p [ i ] [ j ] [ k ] = d p [ i − 1 ] [ j − 1 ] [ k ] + a [ k ] dp[i][j][k] = dp[i - 1][j - 1][k] + a[k] dp[i][j][k]=dp[i−1][j−1][k]+a[k],表示第 i i i 次操作要交换 a [ i − 1 ] a[i - 1] a[i−1] 和 a [ i ] a[i] a[i],而 a [ i − 1 ] a[i - 1] a[i−1] 在上一次操作中已经有 a [ i − 1 ] : = a [ k ] a[i - 1] := a[k] a[i−1]:=a[k];
- d p [ i ] [ j ] [ k ] = d p [ i − 1 ] [ j − ∣ i − k ∣ ] [ k 1 ] + a [ k ] , k 1 < k dp[i][j][k] = dp[i - 1][j - |i - k|][k_1] + a[k], \ k_1 < k dp[i][j][k]=dp[i−1][j−∣i−k∣][k1]+a[k], k1<k。
- 满足的条件有 j − ∣ i − k ∣ ⩾ 0 j - |i - k| \geqslant 0 j−∣i−k∣⩾0,即 max ( 0 , i − j ) ⩽ k ⩽ min ( n , i + j ) \max(0, \ i - j) \leqslant k \leqslant \min(n, \ i + j) max(0, i−j)⩽k⩽min(n, i+j);
- ∣ i − k ∣ |i - k| ∣i−k∣ 表示把 a [ k ] a[k] a[k] 挪到 a [ i ] a[i] a[i] 需要 ∣ i − k ∣ |i - k| ∣i−k∣ 交换;
- 除此之外, k 1 < k k_1 < k k1<k 表示第 i − 1 i - 1 i−1 次操作可以交换到 a [ i − 1 ] a[i - 1] a[i−1] 的为 a [ k 1 ] a[k_1]