Superset
传送门
A set of points on a plane is called good, if for any two points at least one of the three conditions is true:
- those two points lie on same horizontal line;
- those two points lie on same vertical line;
- the rectangle, with corners in these two points, contains inside or on its borders at least one point of the set, other than these two. We mean here a rectangle with sides parallel to coordinates’ axes, the so-called bounding box of the two points.
You are given a set consisting of n n n points on a plane. Find any good superset of the given set whose size would not exceed 2 ⋅ 1 0 5 2·10^{5} 2⋅105 points.
Input
The first line contains an integer n n n ( 1 < = n < = 1 0 4 1<=n<=10^{4} 1<=n<=104 ) — the number of points in the initial set. Next n n n lines describe the set’s points. Each line contains two integers x i x_{i} xi and y i y_{i} yi ( − 1 0 9 < = x i , y i < = 1 0 9 -10^{9}<=x_{i},y_{i}<=10^{9} −109<=xi,yi<=109 ) — a corresponding point’s coordinates. It is guaranteed that all the points are different.
Output
Print on the first line the number of points m m m ( n < = m < = 2 ⋅ 1 0 5 n<=m<=2·10^{5} n<=m<=2⋅105 ) in a good superset, print on next m m m lines the points. The absolute value of the points’ coordinates should not exceed 1 0 9 10^{9} 109 . Note that you should not minimize m m m , it is enough to find any good superset of the given set, whose size does not exceed 2 ⋅ 1 0 5 2·10^{5} 2⋅105 .
All points in the superset should have integer coordinates.
Example
input
2
1 1
2 2
output
3
1 1
2 2
1 2
题目翻译
如果对于任意两个点,三个条件中至少有一个为真,则平面上的一组点称为好点:
- 这两点位于同一条水平线上;
- 这两点位于同一条垂直线上;
- 以这两点为角的矩形在其内部或边界上至少包含集合中除这两点以外的一个点。这里我们指的是边与坐标轴平行的矩形,即所谓的两点的边界框。请找出所给集合中大小不超过 2 ⋅ 1 0 5 2·10^5 2⋅105 个点的任何好的超集。
输入格式
第一行包含一个整数 n ( 1 ≤ n ≤ 1 0 4 ) n(1 ≤ n ≤ 10^4) n(1 ≤ n ≤ 104)-初始集合中的点数。接下来的 n 行描述集合中的点。每行包含两个整数 x i , y i ( − 1 0 9 ≤ x i , y i ≤ 1 0 9 ) x_i,y_i(-10^9 ≤ x_i, y_i ≤ 10^9) xi,yi(−109 ≤ xi, yi ≤ 109)–对应点的坐标。保证所有点都是不同的。
输出格式
在第一行打印好超集中的点数
m
(
n
≤
m
≤
2
⋅
1
0
5
)
m(n ≤ m ≤ 2·10^5)
m(n ≤ m ≤ 2⋅105),在接下来的
m
m
m 行打印点数。点坐标的绝对值不应超过
1
0
9
10^9
109。注意不要最小化
m
m
m,只要找到给定集合中任何一个大小不超过
2
⋅
1
0
5
2·10^5
2⋅105 的良好超集即可。
超集中所有点的坐标都应为整数。
以上来自 C o d e F o r c e s ,翻译: D e e p L 以上来自CodeForces,翻译:DeepL 以上来自CodeForces,翻译:DeepL
解题思路
先将每个点按照 x x x 坐标为第一关键字, y y y 坐标为第二关键字从小到大进行排序。
然后进行分治。对于一个区间 [ l , r ] [l,r] [l,r],以中间点 m i d mid mid 的 x x x 坐标为新增的点的 x x x 坐标, [ l , r ] [l,r] [l,r] 内每个点的 y y y 坐标为新增的点的 y y y 坐标,共构造出 r − l + 1 r−l+1 r−l+1 个点。
最后将原来的点和新增的点一起进行排序,去重即可。
AC Code
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 2e5 + 5;
struct Point {
int x, y;
bool operator<(Point b) {
if (x != b.x) {
return x < b.x;
}
return y < b.y;
}
bool operator==(Point b) {
return x == b.x && y == b.y;
}
};
int n;
Point a[Maxn];
int len;
int Final_len;
inline void partition(int l, int r) {
if (l == r) {
return;
}
int mid = (l + r) >> 1;
for (int i = l; i <= r; i++) {
a[++len] = (Point) {
a[mid].x, a[i].y
};
}
partition(l, mid);
partition(mid + 1, r);
}
inline void work() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y;
}
sort(a + 1, a + n + 1);
len = n;
partition(1, len);
sort(a + 1, a + len + 1);
Final_len = unique(a + 1, a + len + 1) - a - 1;
cout << Final_len << endl;
for (int i = 1; i <= Final_len; i++) {
cout << a[i].x << " " << a[i].y << endl;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
work();
return 0;
}//C++20