[CF475F][平衡树][分治]Meta-universe

CF475F

考虑暴力的做法就是按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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值