【巧用set实现对有序数组O(logn)时间复杂度增、删、查、改、二分操作】codeforces 1041 C. Coffee Break
1.【处理元组有关的题型的技巧】codeforces 1677 A. Tokitsukaze and Strange Inequality
2.【巧用set实现对有序数组O(logn)时间复杂度增、删、查、改、二分操作】codeforces 1041 C. Coffee Break
3.【枚举右,维护左】LeetCode 3404. 统计特殊子序列的数目4.【离线+单调栈】AtCoder ABC379 F. Buildings 25.【离线+LogTrick】codeforces 1878 E. Iva & Pav题意
第一行输入三个整数
在每一天你都可以任意选择一个未选过的数
问:最少需要多少天,可以选完全部的数?
题解
先给结论:先从小到大排序,然后选中剩下的数组的第一个数
疑问解析:为什么优先选择最小的满足
答:不妨假设数组排序后为
接下来分析具体代码实现:
如何在数组中找出第一个比选中的数大
明显可以线性查找,但是当数组中任意两个数的差值均小于
观察我们的前置条件排序,所以可以考虑使用二分法来使得查找的时间复杂度降低为
如何选择过的数从数组中移除呢?
若通过类似插入排序等思路,时间复杂度为
此时思考:既要排序,又要可以二分,还要支持快速删除,我们可以联想到红黑树的性质,但是手撕红黑树太硬核了,可以借助
参考代码
#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; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型