考虑暴力的做法就是按x或y坐标排序然后枚举在哪里切割,这样是
n
2
n^2
n2的
考虑优化,我们从x两边同时往中间扫,对于y也是一样。扫到了就把少的那边分出来,然后两边递归。
加上一个平衡树或者set维护这两个指针就是
n
l
o
g
2
n
nlog^2n
nlog2n
Code:
#include<bits/stdc++.h>
#define sx set<point,cmpx>
#define sy set<point,cmpy>
#define ins insert
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
struct point{
int x,y;
point(){}
point(int _x,int _y):x(_x),y(_y){}
};
struct cmpx{
inline bool operator()(point a,point b){return (a.x^b.x)?a.x<b.x:a.y<b.y;}
};
struct cmpy{
inline bool operator()(point a,point b){return (a.y^b.y)?a.y<b.y:a.x<b.x;}
};
inline bool cmp(point a,point b){return (a.x^b.x)?a.x<b.x:a.y<b.y;}
int solve(sx &xx,sy &yy){
if(xx.size()==1) return 1;
sx xx1;sy sy1;
sx::iterator ix1;sx::reverse_iterator ix2;
sy::iterator iy1;sy::reverse_iterator iy2;
ix1=xx.begin();ix2=xx.rbegin();
iy1=yy.begin();iy2=yy.rbegin();
int t;
do{
t=ix1->x;ix1++;
if(ix1->x-t>1){
while(xx.begin()->x<=t){
point a=*xx.begin();
xx1.ins(a);sy1.ins(a);
yy.erase(a);xx.erase(a);
}
return solve(xx,yy)+solve(xx1,sy1);
}
t=ix2->x;ix2++;
if(t-ix2->x>1){
while(xx.rbegin()->x>=t){
point a=*xx.rbegin();
xx1.ins(a);sy1.ins(a);
yy.erase(a);xx.erase(a);
}
return solve(xx,yy)+solve(xx1,sy1);
}
t=iy1->y;iy1++;
if(iy1->y-t>1){
while(yy.begin()->y<=t){
point a=*yy.begin();
xx1.ins(a);sy1.ins(a);
xx.erase(a);yy.erase(a);
}
return solve(xx,yy)+solve(xx1,sy1);
}
t=iy2->y;iy2++;
if(t-iy2->y>1){
while(yy.rbegin()->y>=t){
point a=*yy.rbegin();
xx1.ins(a);sy1.ins(a);
xx.erase(a);yy.erase(a);
}
return solve(xx,yy)+solve(xx1,sy1);
}
}while(cmp(*ix1,*ix2));
return 1;
}
int main(){
int n=read();
sx xx;sy yy;
for(int x,y,i=1;i<=n;i++){
x=read();y=read();
xx.ins(point(x,y));
yy.ins(point(x,y));
}
cout<<solve(xx,yy);
return 0;
}