2020牛客暑期多校训练营(第三场)E.Two Matchings

2020牛客暑期多校训练营(第三场)E.Two Matchings

题目链接

题目描述

A permutation of length n is an array p = [ p 1 , p 2 , … , p n ] p=[p_1, p_2, \ldots, p_n] p=[p1,p2,,pn], which contains every integer from 1 to n (inclusive) and each number appears exactly once. For example, p = [ 3 , 1 , 4 , 6 , 2 , 5 ] p=[3,1,4,6,2,5] p=[3,1,4,6,2,5] is a permutation of length 6.

Let’s call a permutation is a matching if and only if p i ≠ i p_i \ne i pi=i and p p i = i p_{p_i} = i ppi=i
for all valid i.

You are given an array a = [ a 1 , a 2 , … , a n ] ( 0 ≤ a i ≤ 1 0 9 , n ≥ 4 a=[a_1, a_2, \ldots, a_n] (0 \le a_i \le 10^9 , n \ge 4 a=[a1,a2,,an](0ai109,n4 and n is even). Define the cost of a permutation is ( ∑ i = 1 n a b s ( a i − a p i ) ) / 2 (\sum\limits_{i=1}^n abs(a_i-a_{p_i})) / 2 (i=1nabs(aiapi))/2.

Define two matchings p, q are combinable if and only if p i ≠ q i p_i \ne q_i pi=qi for all i from 1 to n.

Please find two combinable matchings such that the sum of the cost of these two matchings is as small as possible. Output the sum.

输入描述:

The first line contains one integer t ( 1 ≤ t ≤ 5 × 1 0 4 ) (1 \le t \le 5 \times 10^4) (1t5×104) — the number of test cases.

Each test contains two lines. The first line contains one integer n ( n ≥ 4 n ≥ 4 n (n \ge 4n≥4 n(n4n4 and n is even), The second line contains n integers a 1 , a 2 , … , a n ( 0 ≤ a i ≤ 1 0 9 ) a_1, a_2, \ldots, a_n (0 \le a_i \le 10^9) a1,a2,,an(0ai109).

The sum of n across the test cases doesn’t exceed 2 × 1 0 5 2 \times 10^5 2×105.

输出描述:

For each test, output one line which contains only one integer representing the answer of this test.

示例1

输入

2
4
0 8 0 0
6
3 1 4 1 5 9

输出

16
16

比赛时打死也想不到是 DP,果然,想不到方法的题目通通是 DP
网上大部分代码都是直接加的,这边提供一个减的思路,也是题解做法:

  • 此题等价于找一些长度为偶数的环使得这些环恰通过每个点一次, 且所有边的总权重最少。
  • 2k 个点所构成的环的权重和的最小值为最大的权重减最小的权重。
  • 先把所有点的按照权重排序,最佳解一定是出现在每个环都是由排序后连续的点构成。
  • 若某个环长度≥ 8,总是可以拆成一些长度为 4 或 6 的环且总边权更小。
    于是我们就可以把点的权重排序后, 对于前 2k 个点当作子题来动态规划啦,转移时只要枚举最后一个点所在的环长度是 4 还是 6 即可。

AC代码如下:

#include
using namespace std;
const int N=2e5+5;
int t,n,x,a[N],dp[N];
int main()
{
	scanf("%d",&t);
	while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i]=0;
        sort(a+1,a+1+n);
        for(int i=5;i<=n-3;i+=2) dp[i]=max(dp[i-2],dp[i-4]+a[i]-a[i-1]);
        printf("%d\n",2*(a[n]-a[1])-2*dp[n-3]);
	}
}

你可能感兴趣的:(动态规划,牛客)