zoukankan      html  css  js  c++  java
  • [luogu p4447] [AHOI2018初中组]分组

    传送门

    [AHOI2018初中组]分组

    题目描述

    小可可的学校信息组总共有n 个队员,每个人都有一个实力值(a[i])。现在,一年一度的编程大赛就要到了,小可可的学校获得了若干个参赛名额,教练决定把学校信息组的(n) 个队员分成若干个小组去参加这场比赛。

    但是每个队员都不会愿意与实力跟自己过于悬殊的队员组队,于是要求分成的每个小组的队员实力值连续,同时,一个队不需要两个实力相同的选手。举个例子:([1, 2, 3, 4, 5])是合法的分组方案,因为实力值连续;([1, 2, 3, 5])不是合法的分组方案,因为实力值不连续;([0, 1, 1, 2])同样不是合法的分组方案,因为出现了两个实力值为1 的选手。

    如果有小组内人数太少,就会因为时间不够而无法获得高分,于是小可可想让你给出一个合法的分组方案,满足所有人都恰好分到一个小组,使得人数最少的组人数最多,输出人数最少的组人数的最大值。

    注意:实力值可能是负数,分组的数量没有限制。

    输入输出格式

    输入格式

    输入有两行:

    第一行一个正整数n,表示队员数量。
    第二行有n 个整数,第i 个整数a[i]表示第i 个队员的实力。

    输出格式

    输出一行,包括一个正整数,表示人数最少的组的人数最大值。

    输入输出样例

    输入样例 #1

    7
    4 5 2 3 -4 -3 -5
    

    输出样例 #1

    3
    

    说明

    【样例解释】 分为2 组,一组的队员实力值是({4, 5, 2, 3}),一组是({-4, -3, -5}),其中最小的组人数为3,可以发现没有比3 更优的分法了。

    【数据范围】

    对于100%的数据满足:(1≤n≤100000)(|a[i]|≤10^9)

    本题共10 个测试点,编号为1~10,每个测试点额外保证如下:

    • 1~2 (n≤6, 1≤a[i]≤100)
    • 3~4 (n≤1000, 1≤a[i]≤10^5) 且a[i]互不相同
    • 5~6 (n≤100000, a[i])互不相同
    • 7~8 (n≤100000, 1≤a[i]≤10^5)
    • 9~10 (n≤100000, |a[i]|≤10^9)

    分析

    这道题是一道妥妥的贪心。

    我们把每一组都看成一个队列,然后每一次扫到一个人的实力值,就检测看看能不能入队。如果两个队都能入,入人数少的队(因为要求最小的队最大)。有则入,无则新开一个队列。

    (吐槽:这道题我TLE了很久,一直以为是算法的问题,后来才发现是read()函数有问题,原来我写的那个快读有点问题,我就直接把read()函数换成朴素cin就好使了。。)

    代码

    /*
     * @Author: crab-in-the-northeast 
     * @Date: 2020-06-12 23:56:53 
     * @Last Modified by: crab-in-the-northeast
     * @Last Modified time: 2020-06-13 00:22:02
     */
    
    #include <iostream>
    #include <cstdio>
    #include <climits>
    #include <algorithm>
    
    #undef min
    
    inline int min(int a, int b) {
        return a < b ? a : b;
    }
    
    inline int read() {
        int x;
        std :: cin >> x;
        return x;
    }
    
    const int maxn = 100005;
    
    int a[maxn];
    int team_max[maxn];
    int team_num;
    int team_size[maxn];
    int ans = INT_MAX;
    
    int main() {
        int n = read();
        for (int i = 1; i <= n; ++i) a[i] = read();
        std :: sort(a + 1, a + n + 1);//把实力值排序
        for (int i = 1; i <= n; ++i) {
            int chgidx = 0;//记录要添加的组
            int chgnum = INT_MAX;//记录可以加的队中人数最少的那个组的人数
            for (int j = 1; j <= team_num; ++j) {
                if (team_max[j] + 1 == a[i] && team_size[j] < chgnum) {//如果可以入队,且队中人数小于目前的chgnum
                    chgidx = j;
                    chgnum = team_size[j];
                    //更新chgidx和chgnum
                }
            }
    
            if (chgnum == INT_MAX) {//如果没有可以入队的,那么chgnum不会更新,即INT_MAX
                team_max[++team_num] = a[i];
                team_size[team_num] = 1;
                //新开一个队
            } else {
                team_max[chgidx] = a[i];
                ++team_size[chgidx];
                //入队
            }
        }
    
        for (int i = 1; i <= team_num; i++) ans = min(ans, team_size[i]);//查找最小值
        printf("%d
    ", ans);//输出答案
        return 0;
    }
    

    评测结果

    评测记录

  • 相关阅读:
    蓝桥杯程序设计 剪格子
    sql中 1<> 1=1的用处
    form表单的6种提交方式
    js中添加监听,判断是什么事件
    angular iFrame加载资源问题
    报表往子报表里传入list
    struts 文件上传
    获取运行时的泛型类型
    Dao层抽取BaseDao
    SSH整合总结
  • 原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p4447.html
Copyright © 2011-2022 走看看