CF97B Superset 题解 分治

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} 2105 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<=2105 ) 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} 2105 .

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 2105 个点的任何好的超集。

输入格式

第一行包含一个整数 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(109xi,yi 109)–对应点的坐标。保证所有点都是不同的。

输出格式

在第一行打印好超集中的点数 m ( n   ≤   m   ≤   2 ⋅ 1 0 5 ) m(n ≤ m ≤ 2·10^5) m(nm 2105),在接下来的 m m m 行打印点数。点坐标的绝对值不应超过 1 0 9 10^9 109。注意不要最小化 m m m,只要找到给定集合中任何一个大小不超过 2 ⋅ 1 0 5 2·10^5 2105 的良好超集即可。
超集中所有点的坐标都应为整数。

以上来自 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 rl+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
  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值