zoukankan      html  css  js  c++  java
  • Codeforces Round #598 (Div. 3) E. Yet Another Division Into Teams dp

    There are nn students at your university. The programming skill of the ii-th student is aiai. 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 21052⋅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 kk students with programming skills a[i1],a[i2],,a[ik]a[i1],a[i2],…,a[ik], then the diversity of this team is maxj=1ka[ij]minj=1ka[ij]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 nn (3n21053≤n≤2⋅105) — the number of students.

    The second line of the input contains nn integers a1,a2,,ana1,a2,…,an (1ai1091≤ai≤109), where aiai is the programming skill of the ii-th student.

    Output

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

    In the second line print nn integers t1,t2,,tnt1,t2,…,tn (1tik1≤ti≤k), where titi is the number of team to which the ii-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
    input
    Copy
    5
    1 1 3 4 2
    
    output
    Copy
    3 1
    1 1 1 1 1 
    
    input
    Copy
    6
    1 5 12 13 2 15
    
    output
    Copy
    7 2
    2 2 1 1 2 1 
    
    input
    Copy
    10
    1 2 5 129 185 581 1041 1909 1580 8150
    
    output
    Copy
    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][1,1,2,3,4] so the answer is 33. It can be shown that you cannot achieve a better answer.

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

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

    /*大概意思: 这个学校里面有n个学生,你需要给他们分成若干的队伍,每个队伍最少3个人。
    每个队伍定义差异值是这个队伍最强的人和最弱的人的能力值差。
    现在你需要构建若干个队伍,使得差异值的总和最小。*/
    /* 大概思路:先排序,然后选择连续的几个人排成一队
    每个队为最少3个,最多五个因为6个人就可以拆成两队,两队的差值一定比一个队伍的小
    然后 dp*/
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 200005;
    int n,tot=0,ans_pos[maxn],fr[maxn],p[maxn],dp[maxn];
    pair<int,int> k[maxn];
    void dfs(int x) {
        if(x==0)return;
        tot++;
        p[x]=1;
        dfs(fr[x]);
    }
    int main() {
        scanf("%d",&n);
        for(int i=1; i<=n; i++) {
            scanf("%d",&k[i].first);
            k[i].second=i;
        }
        sort(k+1,k+1+n);
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        dp[3]=k[3].first-k[1].first;
        for(int i=4; i<=n; i++) {
            for(int j=3; j<=6; j++) {
                if(dp[i-j]!=-1) {
                    if(dp[i]==-1) {
                        dp[i]=dp[i-j]+k[i].first-k[i-j+1].first;
                        fr[i]=i-j;
                    } else {
                        if(dp[i-j]+(k[i].first-k[i-j+1].first)<dp[i]) {
                            fr[i]=i-j;
                            dp[i]=dp[i-j]+k[i].first-k[i-j+1].first;
                        }
                    }
                }
            }
        }
        dfs(n);
        cout<<dp[n]<<" "<<tot<<endl;
        int tot2=1;
        for(int i=1; i<=n; i++) {
            if(p[i]==0) {
                p[i]=tot2;
            } else if(p[i]==1) {
                p[i]=tot2;
                tot2++;
            }
        }
        for(int i=1; i<=n; i++) {
            ans_pos[k[i].second]=p[i];
        }
        for(int i=1; i<=n; i++) {
            cout<<ans_pos[i]<<" ";
        }
        cout<<endl;
    }
  • 相关阅读:
    数组中最大和的子数组
    数据结构与算法面试题80道
    fcntl获取和修改文件打开状态标志
    dup等复制文件描述符函数
    截断文件函数truncate和ftruncate
    浅析
    五个Taurus垃圾回收compactor优化方案,减少系统资源占用
    如何用交互式特征工程工具进行数据分析处理
    【华为云技术分享】解密如何使用昇腾AI计算解决方案构建业务引擎
    Scrum Master教你四招,瓦解团队内部刺头
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/11804168.html
Copyright © 2011-2022 走看看