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}) 对数之差最小,要找到两个这样的,并且这两个不能有任意一对相同。
最后就是观察出来,要么拆成6,要么拆成4,最后dp一下。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
#define debug(x) printf("debug:%s=%lld
",#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
",dp[n]);
}
}