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;
}