Codeforces 97B Superset 平面分治

题目链接:点击打开链接

题意:

给定一个点集

添加一些点后再把这个点集输出来。

添加完点后使得对于点集内任意2个点都满足下面2条中至少一条

1、在同一水平线上或在同一垂直线上

2、所围成的矩阵里有其他点。

思路:

平面分治

先把点按x轴排序,然后找到中间的点,做一条直线 x = a[mid].x;

然后把所有点都投影到这条直线上,那么对于左边的点就不需要再和右边的进行匹配了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <set>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int inf = 1e9;
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}
#define N 10005
pii a[N], b[N*20];
int top, n;
void dfs(int l, int r){
    int mid = (l+r)>>1, maxx = a[mid].first;
    for(int i = l; i <= r; i++)
        b[top++] = pii(maxx, a[i].second);
    if(l < mid)
        dfs(l, mid-1);
    if(mid < r)
        dfs(mid+1, r);
}
void input(){
    for(int i = 1; i <= n; i++) rd(a[i].first), rd(a[i].second);
    sort(a+1, a+1+n);
    top = 0;
}
void output(){
    sort(b, b+top);
    top = unique(b, b+top)-b;
    pt(top); putchar('\n');
    for(int i = 0; i < top; i++)
        pt(b[i].first), putchar(' '), pt(b[i].second), putchar('\n');
}
int main(){
    while(rd(n)){
        input();
        dfs(1, n);
        output();
    }
    return 0;
}
时间: 2024-08-10 00:07:51

Codeforces 97B Superset 平面分治的相关文章

A - Superset CodeForces - 97B(人生第一个分治法,感觉,像二分啊。。)

/* 分治法,第一次做不是很懂,借鉴了神犇代码,但实操之后感觉像二分,,可能做得少了或者就是.... */ 题目大意: 一个集合里有若干点,要求你添加某些点后保证这个集合里的任意两点满足以下三个条件中至少一个: 1.在一个水平线上 2.在一个竖直线上 3.两点组成的矩形之间有点. 解题思路: 神犇所讲,将点排序,在中间点处建一条竖直线,令其余点在其上投影,二分. ps:不是很明白错误是什么,,结构体里重载<运算符可以,但是写个cmp函数就报错,不是很懂,贴上错误代码,如果神犇们知道什么错误,请评

Luogu 1429 平面最近点对 | 平面分治

Luogu 1429 平面最近点对 题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开. 输出格式: 仅一行,一个实数,表示最短距离,精确到小数点后面4位. 这是一道平面上的分治. 这是一个平面,我们把它分成两半,使x坐标位于最中间的两个点分到左右两侧: 对于同在左侧或同在右侧的点对,我们可以递归处理:

Codeforces - 559B - Equivalent Strings - 分治

http://codeforces.com/problemset/problem/559/B 这个题目,分治就好了,每次偶数层可以多一种判断方式,判断它的时间就是logn的(吧),注意奇数层并不是直接退出!题目给了另一种相等的条件. #include<bits/stdc++.h> using namespace std; #define ll long long char s[200005]; char t[200005]; bool isequal(char *sb,int slen,cha

Codeforces 938G 线段树分治 线性基 可撤销并查集

Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问x到y的路径异或最小值 保证图在任意时刻连通 首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来 有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用

BZOJ 2458 最小三角形 | 平面分治

BZOJ 2458 最小三角形 题面 一个平面上有很多点,求他们中的点组成的周长最小的三角形的周长. 题解 跟平面最近点对差不多,也是先把区间内的点按x坐标从中间分开,递归处理,然后再处理横跨中线的三角形. 如何缩小范围?设左右两个子区间发现的最小周长是d,则与中线距离超过d / 2都没有用了,对于一个点,所有与它距离超过d / 2的点也都没有用. #include <cstdio> #include <cstring> #include <cmath> #includ

CodeForces 196C.Paint Tree(分治+极角排序)

C. Paint Tree time limit per test 2 seconds memory limit per test 256 megabytes You are given a tree with \(n\) vertexes and \(n\) points on a plane, no three points lie on one straight line. Your task is to paint the given tree on a plane, using the

HDU 1007 Quoit Design | 平面分治

暂鸽 #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define N 100010 using namespace std; void chkmin(double x,double y) {if (x>y) x=y;} int n; struct point { double x,y; point(){}; point(double _x,double _

BZOJ 2458: [BeiJing2011]最小三角形 | 平面分治

题目: 给出若干个点 求三个点构成的周长最小的三角形的周长(我们认为共线的三点也算三角形) 题解: 可以参考平面最近点对的做法 只不过合并的时候改成枚举三个点更新周长最小值,其他的和最近点对大同小异 2#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define N 200010 #define INF 1e20 using namespace std; int

Codeforces 1140F 线段树 分治 并查集

题意及思路:https://blog.csdn.net/u013534123/article/details/89010251 之前cf有一个和这个相似的题,不过那个题只有合并操作,没有删除操作,直接并查集搞一搞就行了.对于这个题,因为有删除操作,我们对操作序列建一颗线段树,记录每个操作影响的区间操作就可以了.这里的并查集不能路径压缩,要按秩合并,这样复杂度是O(logn)的. 代码: #include <bits/stdc++.h> #define ls (o << 1) #de