1226E. Yet Another Division Into Teams

time limit per test2 seconds memory limit per test256 megabytes
inputstandard input outputstandard output There are n students at your
university. The programming skill of the i-th student is ai. As a
coach, you want to divide them into teams to prepare them for the
upcoming ICPC finals. Just imagine how good this university is if it
has 2⋅105 students ready for the finals!

Each team should consist of at least three students. Each student
should belong to exactly one team. The diversity of a team is the
difference between the maximum programming skill of some student that
belongs to this team and the minimum programming skill of some student
that belongs to this team (in other words, if the team consists of k
students with programming skills a[i1],a[i2],…,a[ik], then the
diversity of this team is maxj=1ka[ij]−minj=1ka[ij]).

The total diversity is the sum of diversities of all teams formed.

Your task is to minimize the total diversity of the division of
students and find the optimal way to divide the students.

Input The first line of the input contains one integer n (3≤n≤2⋅105) —
the number of students.

The second line of the input contains n integers a1,a2,…,an
(1≤ai≤109), where ai is the programming skill of the i-th student.

Output In the first line print two integers res and k — the minimum
total diversity of the division of students and the number of teams in
your division, correspondingly.

In the second line print n integers t1,t2,…,tn (1≤ti≤k), where ti is
the number of team to which the i-th student belong.

If there are multiple answers, you can print any. Note that you don’t
need to minimize the number of teams. Each team should consist of at
least three students.

Examples inputCopy 5 1 1 3 4 2 outputCopy 3 1 1 1 1 1 1 inputCopy 6 1
5 12 13 2 15 outputCopy 7 2 2 2 1 1 2 1 inputCopy 10 1 2 5 129 185
581 1041 1909 1580 8150 outputCopy 7486 3 3 3 3 2 2 2 2 1 1 1 Note In
the first example, there is only one team with skills [1,1,2,3,4] so
the answer is 3. It can be shown that you cannot achieve a better
answer.

In the second example, there are two teams with skills [1,2,5] and
[12,13,15] so the answer is 4+3=7.

In the third example, there are three teams with skills [1,2,5],
[129,185,581,1041] and [1580,1909,8150] so the answer is
4+912+6570=7486.

//cyc
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define mst(a) memset(a,0,sizeof a)
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int maxn=2e5+5;
const int INF=0x3f3f3f3f;
map<int,int> mpk;
vector<pii> vec;
int dp[maxn];
int flgx[maxn];
int vis[maxn];
int cnt=0;
void dfs(int k)
{
    if(k==0){
        return;
    }
    cnt++;//最优情况序列总数量
    vis[k]=1;
    dfs(flgx[k]);
}
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,v;
    cin>>n;
    vec.pb({0,0});
    for(int i=1;i<=n;i++){
        cin>>v;
        dp[i]=-1;
        vec.pb({v,i});
    }
    mst(flgx);
    sort(vec.begin(),vec.end());

    dp[0]=0;
    for(int i=3;i<=n;i++){

        for(int j=2;j<=min(i-1,5LL);j++){//如果最佳序列长度大于6,拆开后结果仍为最佳
            if(dp[i-j-1]==-1)continue;
            if(dp[i]==-1){
                dp[i]=dp[i-j-1]+vec[i].fi-vec[i-j].fi;
            flgx[i]=i-j-1;//记录上个序列终点
            }
            else{
            if(dp[i]>(dp[i-j-1]+vec[i].fi-vec[i-j].fi)){
            dp[i]=dp[i-j-1]+vec[i].fi-vec[i-j].fi;
            flgx[i]=i-j-1;
            }
            }
        }
    }
    dfs(n);
    int otp=1;
    cout<<dp[n]<<" "<<cnt<<endl;
    for(int i=1;i<=n;i++){

        flgx[vec[i].se]=otp;
        if(vis[i]){
            otp++;
        }
    }
    for(int i=1;i<=n;i++)cout<<flgx[i]<<" ";
    cout<<endl;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值