看大家好多写的都用了四维偏序,给一个不用偏序的解法。
简化一下题目,就是给你 \(n\) 个矩形,第 \(i\) 个矩形用 \((x1_i,y1_i,x2_i,y2_i)\) 表示,问你有多少个 \(i\) 满足:
- 不存在另一个 \(j\) 使得 \(x1_j\le x1_i\le x2_j\wedge y1_j\le y1_i\le y2_j\)。
我们从左到右扫描每一个 \(x\)。
我们建立一个数组,对于每一个 \(i\),我们可以在 \(x=x1_i\) 的时候把数组上的第 \(y1_i\) 个数到第 \(y2_i\) 个数全部加一,在 \(x=x2_i+1\) 的时候再全部减一。
这样对于任意一个 \(i\),我们只要判断当 \(x=x1_i\) 时,数组上的第 \(y1_i\) 个数是否为 \(1\)(这个矩形也在自己内) 就可以知道这个矩形是否在其它的矩形内了,只有这个数为 \(1\),才说明这个矩形不在任何其它的矩形内。
这个数组可以用树状数组维护,时间复杂度 \(O(n\log n)\)。
代码:
#include<bits/stdc++.h>
#define mxn 1000003
using namespace std;
struct node{
int x,i;
};
int n,ans,c[mxn];
bool fl[50003];
vector<pair<int,int> >ad[mxn],dl[mxn];
vector<node>q[mxn];
void add(int x,int y){
for(;x<=1000001;x+=x&-x)c[x]+=y;
}
int ask(int x){
int num=0;
for(;x;x-=x&-x)num+=c[x];
return num;
}
signed main(){
scanf("%d",&n);
for(int i=0,x1,y1,x2,y2;i<n;++i){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
y1++,y2++;
ad[x1].push_back(make_pair(y1,y2));
dl[x2].push_back(make_pair(y1,y2));
q[x1].push_back({y1,i});
}
for(int i=0;i<1000001;++i){
for(pair<int,int>p:ad[i]){
add(p.first,1);
add(p.second+1,-1);
}
for(node j:q[i]){
if(ask(j.x)!=1)fl[j.i]=1;
}
for(pair<int,int>p:dl[i]){
add(p.first,-1);
add(p.second+1,1);
}
}
for(int i=0;i<n;++i)if(!fl[i])ans++;
printf("%d",ans);
return 0;
}
标签:x1,Farm,题解,mxn,int,add,y1,矩形,Painting
From: https://www.cnblogs.com/zifanoi/p/18039985