• 「Codeforces 97B」Superset


    Description

    定义一个点集是“好的”,那么其中任意两点之间满足下列三个条件之一:

    • 横坐标相同
    • 纵坐标相同
    • 以这两个点为顶点的长方形包含(在内部或边缘)其他的至少一个点。

    现在有 (n) 个点,找到一种添加点的方案,使得这个集合是“好的”。

    构造其中一组总点数不超过 (2 imes 10^5) 的可行解。

    Hint

    • (1le nle 10^4)
    • (| ext{坐标大小}| le 10^9)

    Solution

    平面分治

    假如将点按 (x) 坐标排序,取中间点的 (x) 坐标作为中间线的 (x) 坐标,然后对所有点做这个中间线上的 投影,所形成的点就是要添加的点。加入这些点之后,可以发现中间线异侧的点对全都满足条件。

    那同侧的呢?使用 踢皮球大法 递归处理。于是做好了。如果要判断重复点的话只要用一个 set 就好了。

    Code

    /*
     * Author : _Wallace_
     * Source : https://www.cnblogs.com/-Wallace-/
     * Problem : Codeforces 97B Superset 
     */
    #include <algorithm>
    #include <iostream>
    #include <set>
    
    using namespace std;
    const int N = 2e5 + 5;
    
    struct Point {
    	int x, y;
    	inline Point() { }
    	inline Point(int _x, int _y) : x(_x), y(_y) { }
    	inline bool operator < (const Point& t) const {
    		return x != t.x ? x < t.x : y < t.y;
    	}
    } p[N];
    set<Point> points;
    int n;
    
    void solve(int l, int r) {
    	if (l == r) return;
    	int mid = (l + r) >> 1, x = p[mid].x;
    	solve(l, mid), solve(mid + 1, r);
    	
    	for (register int i = l; i <= r; i++)
    		points.insert(Point(x, p[i].y));
    }
    
    signed main() {
    	ios::sync_with_stdio(false);
    	
    	cin >> n;
    	for (register int i = 1; i <= n; i++)
    		cin >> p[i].x >> p[i].y;
    	for (register int i = 1; i <= n; i++)
    		points.insert(p[i]);
    	
    	sort(p + 1, p + 1 + n);
    	solve(1, n);
    	
    	cout << points.size() << endl;
    	for (set<Point>::iterator it = points.begin(); it != points.end(); it++)
    		cout << it->x << ' ' << it->y << endl;
    	return 0;
    }
    
  • 相关阅读:
    NullPointerException异常没有异常栈打印问题追踪
    Nginx服务器的安装和卸载
    线程池——ThreadPoolExecutor
    Nginx简介
    线程池框架简介
    同步工具——Phaser
    你不知道的搜索技巧?
    数据库并发处理
    索引-建立框架篇
    Leetcode 84 求直方图中矩形的最大面积
  • 原文地址:https://www.cnblogs.com/-Wallace-/p/12874003.html
Copyright © 2020-2023  润新知