UVA11020 Efficient Solutions
题目
见链接。
题解
知识点:STL,二分。
首先不考虑新加入的操作,先考虑一个固定的局面,给定了所有人的两个属性值 和 ,找出有竞争力的人。
这类双变量的条件一般可以画在坐标系 查看,发现如果一个点坐标到原点构成的矩形内部(包括边,但不包括这个点本身)有其他点,则这个点就没有竞争力。
于是发现竞争力人群规律, 小的人相对于其他人 会较大,而 大的人相对于其他人 会较小。因为对于一个 小的人,那么后面 大的人 要比 小的人的 小,不然就没竞争力,所以整体会呈现一个反比例函数的形式。
接下来,容器要满足排序,插入,删除,查找,且元素可能重复,因此用 multiset
。为了方便查找,我们对列表按 为第一关键字从小到大排, 为第二关键字从小到大排。
现在考虑插入一个人,我们先在坐标系中往他左边看,判断他能不能插入。具体的说,我们要找到 小于他的人中 最小的人,这个人是最有可能使他失去优势的人。根据我们之前分析的特性, 越大 越小,因此需要找到最后一个 小于他或者 等于他但 小于等于他的人。为此,我们需要使用 lower_bound
找到第一个 大于他或者 等于他但 大于等于他的人,这个人的前一个人就是我们要找的人。如果没有找到,或者找到的人 大于他,那么他就能插入,否则不能。
如果能插入,我们在坐标系中往他右边看,开始排除后面需要踢掉的人。具体的说,我们要踢掉所有 大于他且 大于等于他或者 等于他且 大于他的人。根据我们之前分析的特性, 越大 越小,因此从第一个 大于他或者 等于他但 大于他的人开始踢,我们可以用 upper_bound
实现。随后开始向后遍历,我们只要踢到第一个 小于他的人之前即可,后面的 更小不需要考虑。
最后容器大小就是有竞争力的人的人数。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; struct node { int x, y; friend bool operator<(node a, node b) { return a.x == b.x ? a.y < b.y : a.x < b.x; } }; bool solve() { int n; cin >> n; multiset<node> ms; for (int i = 0, x, y;i < n;i++) { cin >> x >> y; node a = { x,y }; auto it = ms.lower_bound(a);//找到最有可能使a失去优势的人 if (it == ms.begin() || (--it)->y > y) {//a有优势 it = ms.insert(a); it = ms.upper_bound(a);//第一个没有优势的人 while (it != ms.end() && it->y >= y) it = ms.erase(it); } cout << ms.size() << '\n'; } return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; cin >> t; int cnt = 1; while (t--) { cout << "Case #" << cnt++ << ":" << '\n'; if (!solve()) cout << -1 << '\n'; cout << (t ? "\n" : ""); } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16461452.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧