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

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

题解:

这个题目我觉得也有点难,主要是难以想到就dp 4和6。

首先 \(p_i!=i \,\,and \,\,p_{pi}=i\) 可得如果 \(p_x=i\) ,那么 \(p_i=x\)

所以再来看这个要求的式子:\((\sum_{i=1}^{n}abs(a_i-a_{pi}))/2\)

可以知道一定存在 \(a_i=a_{pi}\)\(a_{pi}-a_i\) ,把这个2消去,所以最后就变成了对于这n个数,找到 \(\frac{n}{2}\) 对数之差最小,要找到两个这样的,并且这两个不能有任意一对相同。

image-20200720211621393

最后就是观察出来,要么拆成6,要么拆成4,最后dp一下。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
#define debug(x) printf("debug:%s=%lld\n",#x,x);
//#define debug(x) cout << #x << ": " << x << endl
using namespace std;
const int maxn = 2e6+10;
typedef long long ll;
ll pre1[maxn],pre2[maxn];
ll dp[maxn],a[maxn];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) dp[i]=inf64,scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        dp[0]=0;
        for(int i=1;i<=n;i+=2) dp[0]+=a[i+1]-a[i];
        for(int i=4;i<=n;i++) pre1[i]=a[i]+a[i-1]-a[i-2]-a[i-3];
        for(int i=6;i<=n;i++) pre2[i]=a[i]+a[i-1]+a[i-3]-a[i-2]-a[i-4]-a[i-5];
        for(int i=4;i<=n;i++){
            if(i>=4) dp[i]=min(dp[i],dp[i-4]+pre1[i]);
            if(i>=6) dp[i]=min(dp[i],dp[i-6]+pre2[i]);
        }
        printf("%lld\n",dp[n]);
    }
}


posted @ 2020-07-20 21:29  EchoZQN  阅读(134)  评论(0编辑  收藏  举报