CodeForces - 97B_Superset_分治

题意

给出平面上 n 个点的坐标(最多 1e4 个),要往其上增加若干点,使得加点后,平面上任意两点至少满足下列三条件之一:
1。两点横坐标相同
2。两点纵坐标相同
3。以两点为对角的矩形中(含边线),至少含义一个其他点。
要求新加入点不超过 2e5。

思路

首先找到中间那个点,即 mid = (1 + n) / 2。过这个点作一条垂直于 x 轴的直线,不在这条直线上的其他点在这条直线上的正投影都增加到平面上。增加之后,直线上任意一点和平面上现有的任意一点构成的点对必满足上述条件。并且,任意一对被直线分隔开的点,也必定满足上述条件。不被直线分隔的点对仍可能不满足条件。
所以,题目转化为确保任意两点之间至少有一条这样的直线分隔。用分治的思想解决。
经过第一步之后,原问题实际上分成了两个与原问题相同的子问题:直线左边的点 和 直线右边的点。情况与原问题相同。所以,递归地过每一个子问题中间的点作垂直于 x 轴的直线,将子问题中的其他点的投影加入,将子问题继续细分直到不可分。
这样最多加入 nlogn 个节点,必小于 2e5。完美解决。

链接

https://vjudge.net/contest/177348#problem/J

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>

using namespace std;

const int maxn = 1e4 + 10;

typedef pair<int, int> P;

int n;
P A[maxn];
set<P> se;
set<P>::iterator it;

void dfs(int l, int r)
{
    int mid = (l + r) >> 1;
    int x = A[mid].first;

    for(int i = l; i <= r; i++)
        se.insert(P(x, A[i].second));

    if(l < mid) dfs(l, mid);
    if(mid < r) dfs(mid + 1, r);
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d %d", &A[i].first, &A[i].second);
    sort(A + 1, A + n + 1);

    dfs(1, n);

    cout << se.size() << endl;

    for(it = se.begin(); it != se.end(); it++)
        cout << it->first << " " << it->second << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值