题意

第一行输入三个整数 \(n,m,d(1 \leq n \leq 2 * 10^5, n \leq m \leq 10^9, 1 \leq d \leq n)\),第二行输入 \(n\) 个整数,保证每个数均不大于 \(m\)。

在每一天你都可以任意选择一个未选过的数 \(a_i\),随后可以继续选任意一个大于 \(a_i + d\) 的数 \(a_j\);接下来可以再选任意一个大于 \(a_j + d\) 的数 \(a_k\);最后重复执行上述步骤。

问:最少需要多少天,可以选完全部的数?

题解

先给结论:先从小到大排序,然后选中剩下的数组的第一个数 \(a_0\),随后选中数组中第一个满足 \(a_i \geq a_0 + d + 1\) 的数 \(a_i\),下一步再选中数组中第一个满足 \(a_j \geq a_i + d\) 的数 \(a_j\),形成的子数组数目便是答案。

疑问解析:为什么优先选择最小的满足 \(a_j \geq a_i + d + 1\)的数是正确的?

答:不妨假设数组排序后为 \(a_0, a_1, ..., a_i, a_j, ..., a_n\),且 \(a_i\) 是最小的满足大于 \(a_0 + d\) 的数。那么明显在选中 \(a_0\) 的下一步,既可以选择 \(a_i\),也可以选择 \(a_j\)。此时若 \(a_j - a_i \leq d\),那明显二者至多只能够选其一,那么无论选择哪一个,都必然意味着需要另外再选择出一个子数组。但如果 \(a_j - a_i \geq d + 1\),就可以先选 \(a_i\) 而后一并选上 \(a_j\)。因此,先选较小者更优。

接下来分析具体代码实现:

如何在数组中找出第一个比选中的数大 \(d\) 以上的数呢?

明显可以线性查找,但是当数组中任意两个数的差值均小于 \(d\) 时,时间复杂度为 \(O(n^2)\),明显不符合要求

观察我们的前置条件排序,所以可以考虑使用二分法来使得查找的时间复杂度降低为 \(O(logn)\)

如何选择过的数从数组中移除呢?

若通过类似插入排序等思路,时间复杂度为 \(O(n^2)\),明显不符合要求

此时思考:既要排序,又要可以二分,还要支持快速删除,我们可以联想到红黑树的性质,但是手撕红黑树太硬核了,可以借助 \(set\) 或 \(map\) 实现,这二者的查找/插入/删除/修改操作时间复杂度都是 \(O(logn)\),符合时间复杂度要求。

参考代码

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
using namespace std; constexpr int INF = 0x3f3f3f3f;
constexpr int N = 2e5 + 7;
int n, m, d, cnt, a;
int ans[N]; int main() {
IOS
set<PII> st;
cin >> n >> m >> d;
for (int i = 0; i < n; ++ i) {
cin >> a;
st.insert(PII(a, i));
}
while (!st.empty()) {
auto f = st.begin();
int key = (*f).first;
ans[(*f).second] = ++ cnt;
st.erase(f);
while (!st.empty()) {
auto ne = st.upper_bound(PII(key + d, INF));
if (ne != st.end()) {
key = (*ne).first;
ans[(*ne).second] = cnt;
st.erase(ne);
} else break;
}
}
cout << cnt << '\n';
for (int i = 0; i < n; ++ i) cout << ans[i] << ' ';
return 0;
}

【巧用set实现对有序数组O(logn)时间复杂度增、删、查、改、二分操作】codeforces 1041 C. Coffee Break的更多相关文章

  1. [LeetCode]105. 从前序与中序遍历序列构造二叉树(递归)、108. 将有序数组转换为二叉搜索树(递归、二分)

    题目 05. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 题解 使用HashMap记录当前子树根节点在中序遍历中的位置,方便每次 ...

  2. iOS常用算法之两个有序数组合并, 要求时间复杂度为0(n)

    思路: 常规思路: 先将一个数组作为合并后的数组, 然后遍历第二个数组的每项元素, 一一对比, 直到找到合适的, 就插入进去; 简单思路: 设置数组C, 对比A和B数组的首项元素, 找到最小的, 就放 ...

  3. 使用C语言封装数组,动态实现增删改查

    myArray.h : #pragma once //包含的时候只包含一次 #include <stdio.h> #include <stdlib.h> #include &l ...

  4. 【算法】字典的诞生:有序数组 PK 无序链表

    参考资料 <算法(java)>                           — — Robert Sedgewick, Kevin Wayne <数据结构>       ...

  5. 两个有序数组的上中位数和第K小数问题

    哈,再介绍个操蛋的问题.当然,网上有很多解答,但是能让你完全看懂的不多,即便它的结果是正确的,可是解释上也是有问题的. 所以,为了以示正听,我也做了分析和demo,只要你愿意学习,你就一定能学会,并且 ...

  6. 【算法】实现字典API:有序数组和无序链表

    参考资料 <算法(java)>                           — — Robert Sedgewick, Kevin Wayne <数据结构>       ...

  7. [LeetCode] Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  8. [LeetCode] Convert Sorted Array to Binary Search Tree 将有序数组转为二叉搜索树

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 这道 ...

  9. [LeetCode] Merge Sorted Array 混合插入有序数组

    Given two sorted integer arrays A and B, merge B into A as one sorted array. Note:You may assume tha ...

  10. [LeetCode] Remove Duplicates from Sorted Array 有序数组中去除重复项

    Given a sorted array, remove the duplicates in place such that each element appear only once and ret ...

随机推荐

  1. Maven高级——多环境配置与应用

    多环境配置与应用 开发步骤 定义多环境 <!--配置多环境--> <profiles> <!--开发环境--> <profile> <id> ...

  2. 《Vue.js 设计与实现》读书笔记 - 第8章、挂载与更新

    第8章.挂载与更新 8.1 挂载子节点和元素的属性 扩展子元素的类型可以为数组,并判断如果是数组的话,就先依次挂载所有的子元素. 同时新增节点属性.属性可以通过 el.setAttribute 添加到 ...

  3. 2024-10-08:用go语言,给定一个字符串 word 和一个整数 k,判断是否可以通过删除最少数量的字符使得该字符串成为 k 特殊字符串。 其中,k 特殊字符串满足字符串中任意两个字符的出现频率

    2024-10-08:用go语言,给定一个字符串 word 和一个整数 k,判断是否可以通过删除最少数量的字符使得该字符串成为 k 特殊字符串. 其中,k 特殊字符串满足字符串中任意两个字符的出现频率 ...

  4. USB configfs与USB functionfs的区别及关系

    configfs 和 functionfs 是 Linux 内核中用于配置和管理 USB 设备行为的两种不同的文件系统,它们各自的用途和工作方式有所不同,但在 USB Gadget 子系统中可以结合使 ...

  5. pip下载太慢,换源

    1.安装pqi pip install pqi 2.改变pip源 比如换成清华源: pqi use tuna 3.显示当前源

  6. 【墨天轮专访第四期】华为云GaussDB苏光牛:发挥生态优势,培养应用型DBA

    导读: 随着5G互联网时代的来临,各行各业对于数据库的依赖程度也在逐步提高.由于国内在数据库行业的发展起步较晚,数据库的市场份额长期被Oracle,微软等美国公司所控制.但是伴随着国内IT技术栈的不断 ...

  7. C# Webapi Filter 过滤器 - 生命周期钩子函数 - Exception Filter 基础

    什么是Filter ? 1. 切面编程机制,在 ASP.NET Core 特定的位置执行我们自定义的代码: 2. ASP.NET Core 中的Filter五种类型,Authorization ,fi ...

  8. 000 通过 Pytorch 实现 Transformer 框架完整代码(带注释)

    博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...

  9. MySQL数据的导出

    有时需要将MySQL数据库中的数据导出到外部存储文件中,MySQL数据库中的数据可以导出成sql文本文件.xml文件或者html文件.本节将介绍数据导出的常用方法. 11.4.1  使用SELECT- ...

  10. onethink自带编辑器内容无法修改

    楼主小白一个,之前有大神带着进入onethink框架 在一个编辑页里面放两个编辑框的时候,悲催了--- 一个用作文本编辑,一个用于多图上传 发现前面的文本编辑的内容无法实现,后来楼主想调试一下 之前提 ...