首页 > 编程语言 >「ACM 算法实践」[解题报告]组队

「ACM 算法实践」[解题报告]组队

时间:2023-03-22 17:59:23浏览次数:35  
标签:int ACM 组队 队伍 解题 mathcal include 人数 getchar

分析

因为时间不多了,我一开始只考虑了 \(a_i\) 互不相等的情况,没想到居然拿到了 60 昏(

正确解法是贪心 + 优先队列。而不是从「使得人数最少的队伍人数最多」中得到的二分

首先肯定要将 a 数组排序,要使人数最少的队伍人数最多,我们优先将当前的数 \(a[i]\) 放到以 \(a[i]-1\) 结尾的队伍中人数最少的一个队伍即可。思路很简单,这题的难点在于怎么实现。

如果用一个 queue 来储存当前已经有了的队伍,然后再暴力查找符合要求的人数最少的队伍,时间复杂度 \(\mathcal{O}(n^2)\) ,肯定会 T ,于是我们考虑用优先队列来存储每条队伍的人数,查找时只需输出队头即可,这时候又如何存储每条队伍最后一个元素呢?可以开 n 条优先队列,q[i] 表示以 a[i] 结尾的所有队伍的人数,同时我们还需要对 a[i] 进行离散化,这样一来,分别为每一个人分队是 \(\mathcal{O}(n)\) 的,priority_queue 的操作是 \(\mathcal{O}(n\log{n})\) 的,所以 总复杂度是 \(\mathcal{O}(n\log{n})\) 。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <unordered_map>
#include <algorithm>
#define DEBUG puts("ok")
using namespace std;

int gi() {
    char c = getchar(); int x = 0, f = 1;
    for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

const int N = 1e5 + 5;

int n, m, ans;
int a[N], b[N], cnt[N];

priority_queue <int, vector<int>, greater<int> > q[N];

int main() {
    n = gi();
    for (int i = 1; i <= n; ++i) a[i] = gi(), b[i] = a[i];
    sort(a + 1, a + 1 + n), sort(b + 1, b + 1 + n);
    m = unique(b + 1, b + 1 + n) - b - 1;
    int k = 1;
    for (int i = 1; i <= m; ++i)
        while (a[k] == b[i]) cnt[i]++, k++;
    for (int i = 1; i <= cnt[1]; ++i) q[1].push(1);
    for (int i = 2; i <= m; ++i) {
        if (b[i] == b[i - 1] + 1) {
            while (q[i - 1].size() && cnt[i]) {
                q[i].push(q[i - 1].top() + 1);
                q[i - 1].pop();
                cnt[i]--;
            }
            if (cnt[i]) {
                while (cnt[i])
                    q[i].push(1), cnt[i]--;
            }
        }
        else {
            while (cnt[i])
                q[i].push(1), cnt[i]--;
        }
    }
    ans = n;
    for (int i = 1; i <= m; ++i)
        if (q[i].size()) ans = min(ans, q[i].top());
    printf("%d", ans);
    return 0;
}

标签:int,ACM,组队,队伍,解题,mathcal,include,人数,getchar
From: https://www.cnblogs.com/huangliwen/p/17244908.html

相关文章

  • 「ACM 算法实践」[解题报告]时间管理大师
    分析一开始想着应该要分情况讨论,如果每台电脑的耗电量都小于\(e\),那么可以知道小Q是可以一直学习下去的,如果存在电脑的耗电量大于等于\(e\),贪心的想法是将每台电脑......
  • 「ACM 算法实践」[解题报告]沙滩拾贝
    分析因为是与运算,只有当这\(m\)个数的第\(k\)位上都是\(1\)的时候才能使得最后的数的第\(k\)位为\(1\)。为了让最后的开心程度最大,我们优先将高位取\(1\),也......
  • 「解题报告」ARC128F Game against Robot
    好厉害的题。震撼到了。大部分参考Atcoder计数乱做-苹果蓝17。我的观察能力还是太差,一点条件都观察不出来,连\(p\)固定怎么做都不会。下面令\(n\gets\frac{n}{2......
  • 剑指 Offer 07. 重建二叉树(java解题)
    目录1.题目2.解题思路个人思路3.数据类型功能函数总结4.java代码1.题目输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍......
  • 「解题报告」ARC128E K Different Values
    我还是很菜啊。先考虑判定问题。考虑先找出一些显然的必要条件。记\(m=\suma_i\)。那么我们首先对\(m\)进行分块,每\(k\)个一块,设块数为\(p\),最后一个块的大小为......
  • 「解题报告」ARC128D Neq Neq
    我果然还是适合做这种简单数数,难的我根本不会做,哈哈!首先我们发现,如果有两个完全相同的相邻的数,那么这两个数中的每一个数都不能够被删除,那么这实际上把整个序列分成了若干......
  • cf1774f解题报告
    MagicianandPigs分析一下三个操作分别干了些什么新添一只猪使血量为\(x\)的猪血量变为\(\max(x-v,0)\)设前面操作后猪总共会受到\(s\)的伤害,复制一只血量为\(......
  • 关于ACM中-由AWS颁发的证书过期前的自动更新说明-及注意事项
    在aws的ACM-(AmazonCertificateManager )中,证书除了可以自己导入,也可以使用AWS颁发,如下图所示,可以看到证书类型当然今天笔者讲述关于使用了AWS颁发证书的,快要到期的时......
  • 关于AWS-ACM-自己导入型Imported-证书的更新替换
    在AWS中,ACM即AmazonCertificateManager的意思,是用来存储管理证书的一个服务ACM的证书有两种类型、一种是由AWS颁发的证书,另一种还可以将自己的证书导入进来,进行管理......
  • 「解题报告」ARC130E Increasing Minimum
    想法大概差不多,但是确实不知道咋维护(考虑每次删最小值的过程,我们相当于先删掉所有最小值\(=1\)的位置,然后删所有最小值\(=2\)的位置,依次类推。那么我们可以将删除的......