zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校第三场E-Two Matchings(规律DP)

    题目大意:给你一个数列,从$a_1->a_n$,你需要找到两个匹配序列$p,q$其中$p_i eq q_i$,使得$(sum_{i=1}^{n}abs(a_i-a_{p_i}))/2+(sum_{i=1}^{n}abs(a_i-a_{q_i}))/2$最小,问这个最小值是多少。n保证为偶数,sum(n)<=2e5

    输入

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

    输出

    16
    16

    如果只是找一个序列的话很好找,我们将a排序,则可得1 2 3 4 5 6这样的有序数列,直接相邻两个相减就是最小值了。我们可以保留这个最小值,接下来我们找次小值,那么就是将数列向前移动一格,第一个数到末尾,然后相邻两个相减,那么这个是次优的。

    但很明显,这样做是有限制的,而显然,对于长度为4的序列,这个规律也成立。对于长度为8的序列,他可以拆成两个长度为4的序列,在这之后的数就可以由多个长度为4的和6的拼接而成。那么也就是说我们可以用DP来维护这个次小值。

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int mac=2e5+10;
    
    int a[mac];
    ll dp[mac];
    
    int main(int argc, char const *argv[])
    {
        int t;
        scanf ("%d",&t);
        while (t--){
            int n;
            scanf ("%d",&n);
            for (int i=1; i<=n; i++)
                scanf ("%d",&a[i]);
            sort(a+1,a+1+n);
            ll ans=0;
            for (int i=1; i<=n; i+=2)
                ans+=a[i+1]-a[i];
            if (n>=4) dp[4]=a[3]-a[2]+a[4]-a[1];
            if (n>=6) dp[6]=a[3]-a[2]+a[5]-a[4]+a[6]-a[1];
            if (n>=8) dp[8]=a[3]-a[2]+a[4]-a[1]+a[7]-a[6]+a[8]-a[5];
            for (int i=10; i<=n; i+=2){
                ll s4=a[i]-a[i-3]+a[i-1]-a[i-2];
                ll s6=a[i]-a[i-5]+a[i-1]-a[i-2]+a[i-3]-a[i-4];
                dp[i]=min(dp[i-4]+s4,dp[i-6]+s6);
            }
            printf("%lld
    ",ans+dp[n]);
        }
        return 0;
    }
    路漫漫兮
  • 相关阅读:
    B. Vova and Trophies 字符串预处理+思维+贪心
    Got error 28 from storage engine
    TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    mysql复制问题
    upgrade mysql
    replica set remove member
    Perl安装及环境配置
    Django
    mongo collection name—SyntaxError: identifier starts immediately after numeric literal
    MySQL 单表flashback
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13351790.html
Copyright © 2011-2022 走看看