按 x 降序、y 降序排序后一次扫描:已扫过点都满足 x' ≥ x,故当前点被支配当且仅当 y 不大于已扫过的最大 y,判定降为 O(1),总复杂度 O(n log n)。
OJ: roj
题目 ID: 1230
难度:入门
标签:入门排序贪心python
创建: 2026-09-30 00:42
更新: 2026-10-05 06:04
题目描述
平面上有
样例:
思路
按
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-30 00:42
# update_at: 2026-09-30 00:42
import sys
def maximal_points(points: list[tuple[int, int]]) -> list[tuple[int, int]]:
"""按 x 从小到大返回所有极大点(没有任何其它点同时不小于它的 x 与 y)。
按 x 降序、y 降序扫描:已扫过的点 x 都不小于当前点,其中最大的 y 记为 max_y。
当前点被支配 <=> 存在已扫过的点 y' >= y <=> y <= max_y,故 y > max_y 即为极大点。
"""
found: list[tuple[int, int]] = []
max_y = -1 # 坐标非负,-1 是比任何真实 y 都小的哨兵
for x, y in sorted(points, reverse=True): # 元组排序:x 降序,x 相同则 y 降序
if y > max_y:
found.append((x, y))
max_y = y
return found[::-1] # 扫描得到 x 递减,反转即为题目要求的 x 递增
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
n = next(data)
points = [(next(data), next(data)) for _ in range(n)]
print(','.join(f'({x},{y})' for x, y in maximal_points(points)))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 06:04
* update_at: 2026-10-05 06:04
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 105;
struct Point {
ll x;
ll y;
} p[MAXN]; // 输入点集
Point ans[MAXN]; // 极大点结果,按 x 递增存放
int ans_cnt; // 极大点个数
// 按 x 降序排序,x 相同时按 y 降序
bool cmp(Point a, Point b) {
if (a.x != b.x) return a.x > b.x;
return a.y > b.y;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> p[i].x >> p[i].y;
}
sort(p + 1, p + n + 1, cmp);
ll max_y = -1; // 坐标非负,-1 作为比所有真实 y 都小的哨兵
for (int i = 1; i <= n; i++) {
// 已扫过的点 x 都不小于当前点,只需判断 y 是否大于已扫最大 y
if (p[i].y > max_y) {
ans[++ans_cnt] = p[i];
max_y = p[i].y;
}
}
// 扫描结果 x 递减,反转后得到题目要求的 x 递增顺序
for (int i = ans_cnt; i >= 1; i--) {
cout << '(' << ans[i].x << ',' << ans[i].y << ')';
if (i > 1) cout << ',';
}
cout << '\n';
return 0;
}