AHOI2008 矩形

7 篇文章 0 订阅
5 篇文章 0 订阅

Description

  第一象限内有N个平行于坐标轴的矩形。你的任务非常简单,那就是计算有多少个矩形,至少被一个矩形包含。

Input

  第一行包含一个整数N,表示矩形的个数。接下来N行,每行用4个整数x1,y1,x2,y2描述了一个矩形。其中(x1,y1)表示这个矩形左下角的坐标,(x2,y2)表示右上角的坐标。

Output

  只包含一个整数,表示你得到的答案。

Sample Input

3
0 0 5 5
1 2 3 4
2 1 4 3

Sample Output

2

Hint

[样例说明]
编号为2和3的矩形被编号为1的矩形包含

[数据规模]
- 50%的数据中,N<=5000
- 100%的数据中,N<=200000
- 所有数据中,一个x值或y值最多出现一次

cdq模板题,可以转化为四维偏序,又因为这道题仅需判定0/1,所以可以降成三维。

具体来说:Ax1<Bx1&&Ax2>Bx2&&Ay1<By1&&Ay2>By2,前两维模板操作,后两维用数据结构乱搞(并没有具体

顺便强行4维偏序一波(然而nlog^2n在本oj 卡成暴力分,洛谷不开o2tle一组)。

#include<bits/stdc++.h>
using namespace std;
const int Maxn=200005;
inline int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))(res*=10)+=c-'0',c=getchar();
	return res;
}
struct Matrix{
	int x1,y1,x2,y2,idx;
	Matrix(int x1=0,int y1=0,int x2=0,int y2=0,int idx=0):x1(x1),y1(y1),x2(x2),y2(y2),idx(idx){}
}a[Maxn];
int n,mx,tmp[Maxn];
bool f[Maxn];
bool cmp1(const Matrix&A,const Matrix&B){
	return A.x1<B.x1;
}
bool cmp2(const Matrix&A,const Matrix&B){
	return A.x2>B.x2;
}
struct ZKW{
	int M,mx[Maxn*10];
	void build(int N){
		memset(mx,-63,sizeof(mx));
		for(M=1;M<N+4;M<<=1);
	}
	void edit(int x,int k){
		mx[x+=M+2]=k;
		while(x>>=1)mx[x]=max(mx[x<<1],mx[x<<1|1]);
	}
	int query(int s,int t){
		int Ans=-0x3f3f3f3f;
		for(s+=M+1,t+=M+3;s^t^1;s>>=1,t>>=1){
			if(~s&1)Ans=max(Ans,mx[s^1]);
			if( t&1)Ans=max(Ans,mx[t^1]);
		}
		return Ans;
	}
}zkw;
void discrete(){
	for(int i=1;i<=n;++i)
		tmp[++tmp[0]]=a[i].y1;
	sort(tmp+1,tmp+tmp[0]+1);
	mx=unique(tmp+1,tmp+tmp[0]+1)-tmp-1;
	for(int i=1;i<=n;++i)
		a[i].y1=lower_bound(tmp+1,tmp+mx+1,a[i].y1)-tmp;
}
void cdq(int l,int r){
	if(l>=r)return ;
	int mid=l+r>>1;
	cdq(l,mid),cdq(mid+1,r);
	sort(a+l,a+mid+1,cmp2),sort(a+mid+1,a+r+1,cmp2);
	int i=l,j=mid+1;
	for(;j<=r;++j){
		for(;i<=mid&&a[i].x2>=a[j].x2;++i)
			zkw.edit(a[i].y1,a[i].y2);
		f[a[j].idx]|=(zkw.query(1,a[j].y1)>=a[j].y2);
	}
	while(--i>=l)zkw.edit(a[i].y1,-0x3f3f3f3f);
}
int main(){
	n=getint();
	for(int i=1;i<=n;++i){
		int x1=getint(),y1=getint(),x2=getint(),y2=getint();
		a[i]=(Matrix){x1,y1,x2,y2,i};
	}
	sort(a+1,a+n+1,cmp1);
	discrete();
	zkw.build(mx);
	cdq(1,n);
	int Ans=0;
	for(int i=1;i<=n;++i)
		Ans+=f[i];
	cout<<Ans<<endl;
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int Maxn=200005;
inline int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))(res*=10)+=c-'0',c=getchar();
	return res;
}
struct Matrix{
	int x1,y1,x2,y2,idx,part;
	Matrix(int x1=0,int y1=0,int x2=0,int y2=0,int idx=0):x1(x1),y1(y1),x2(x2),y2(y2),idx(idx){}
}a[Maxn],t[Maxn];
int n,mx,tmp[Maxn];
bool f[Maxn];
bool cmp1(const Matrix&A,const Matrix&B){
	return A.x1<B.x1;
}
bool cmp2(const Matrix&A,const Matrix&B){
	return A.x2>B.x2;
}
struct ZKW{
	int M,mx[Maxn*10];
	void build(int N){
		memset(mx,-63,sizeof(mx));
		for(M=1;M<N+4;M<<=1);
	}
	void edit(int x,int k){
		mx[x+=M+2]=k;
		while(x>>=1)mx[x]=max(mx[x<<1],mx[x<<1|1]);
	}
	int query(int s,int t){
		int Ans=-0x3f3f3f3f;
		for(s+=M+1,t+=M+3;s^t^1;s>>=1,t>>=1){
			if(~s&1)Ans=max(Ans,mx[s^1]);
			if( t&1)Ans=max(Ans,mx[t^1]);
		}
		return Ans;
	}
}zkw;
void discrete(){
	for(int i=1;i<=n;++i)
		tmp[++tmp[0]]=a[i].y1;
	sort(tmp+1,tmp+tmp[0]+1);
	mx=unique(tmp+1,tmp+tmp[0]+1)-tmp-1;
	for(int i=1;i<=n;++i)
		a[i].y1=lower_bound(tmp+1,tmp+mx+1,a[i].y1)-tmp;
}
void cdq2(int l,int r){//part=-1:x1<x1',x2降序
	if(l>=r)return ;
	int mid=l+r>>1;
	cdq2(l,mid),cdq2(mid+1,r);
	int i=l,j=mid+1;
	for(;j<=r;++j){
		for(;i<=mid&&t[i].x2>=t[j].x2;++i)//这道题可以一个for到底 
			if(t[i].part==-1)zkw.edit(t[i].y1,t[i].y2);
		if(t[j].part==1)f[t[j].idx]|=(zkw.query(1,t[j].y1)>=t[j].y2);
	}
	while(--i>=l)zkw.edit(t[i].y1,-0x3f3f3f3f);
}
void cdq1(int l,int r){//x1升序 
	if(l>=r)return ;
	int mid=l+r>>1;
	cdq1(l,mid),cdq1(mid+1,r);
	sort(a+l,a+mid+1,cmp2),sort(a+mid+1,a+r+1,cmp2);
	int i=l,j=mid+1,cnt=l-1;
	while(i<=mid&&j<=r){
		if(a[i].x2>=a[j].x2){
			t[++cnt]=a[i++];
			t[cnt].part=-1;
		}else {
			t[++cnt]=a[j++];
			t[cnt].part=1;
		}
	}
	while(i<=mid)t[++cnt]=a[i++],t[cnt].part=-1;
	while(j<=r)t[++cnt]=a[j++],t[cnt].part=1;
	//重标号
	cdq2(l,r);
}
int main(){
	n=getint();
	for(int i=1;i<=n;++i){
		int x1=getint(),y1=getint(),x2=getint(),y2=getint();
		a[i]=(Matrix){x1,y1,x2,y2,i};
	}
	sort(a+1,a+n+1,cmp1);
	discrete();
	zkw.build(mx);
	cdq1(1,n);
	int Ans=0;
	for(int i=1;i<=n;++i)
		Ans+=f[i];
	cout<<Ans<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值