Codeforces Round #598 (Div. 3) E

传送门

AC代码

/*
先排序,因为取连续的一段数作为一队,diff肯定是优于不连续的
当一段>=6时,一定能分成两队,diff4-diff3可以被优化掉
所以 就有了递推式 dp[i] = min ( dp[i] , dp[i-j] + a[i] - a[i-j+1] ), 3<=j<=5;
*/

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int N=1e6+5;
#define ls (i<<1)
#define rs (i<<1|1)
#define fi first
#define se second
#define mk make_pair
#define mem(a,b) memset(a,b,sizeof(a))
LL read()
{
    LL x=0,t=1;
    char ch=getchar();
    while(!isdigit(ch)){ if(ch=='-')t=-1; ch=getchar(); }
    while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    return x*t;
}
pLL a[N];
LL dp[N],path[N];
int ans[N];
int main()
{
    int n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].fi=read();
        a[i].se=i;
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) path[i]=1;
    mem(dp,0x3f); dp[0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=3;j<=5&&i-j>=0;j++)
        {
            int tmp=dp[i-j]+a[i].fi-a[i-j+1].fi;
            //printf("i=%d dp=%d
",i,dp[i]);
            if(tmp<dp[i])
            {
                dp[i]=tmp;
                path[i]=i-j+1;
            }
            //else if(tmp==dp[i]&&)
        }
    }
    int cnt=1,m=n;

    while(m)
    {
        for(int i=m;i>=path[m];i--)
            ans[a[i].se]=cnt;
        m=path[m]-1;
        cnt++;
    }
    printf("%lld %d
",dp[n],cnt-1);
    for(int i=1;i<=n;i++)
        printf("%d%c",ans[i],i==n?'
':' ');
    return 0;
}
原文地址:https://www.cnblogs.com/DeepJay/p/12025179.html