This way
有一个矩形在平面上,它的左下右上角是(0,0),(1e6,1e6)
现在给你一些水平或者竖直的线段,在这个矩形内部并且至少有一端和这个矩形相交,问你这些线段将这个矩形分成多少个部分
我们枚举每个竖直的线段,然后查看它和多少个水平的线段相交,由于每个线段一定都和矩形相交,那么这个线段在内部的相交数就是它的贡献(这道题应该去年做到过)
并且两端都与矩形相交的线段,它的贡献会增加1.
#include
using namespace std;
#define ll long long
const int N=1e6+5,M=1e6;
int sum[N*4];
unordered_map<int,vector<int> >sta,en;
struct node{
int p,x,y;
bool operator< (const node& a)const {
return p<a.p;
}
}h[N/10+5],v[N/10+5];
int b[N];
void update(int l,int r,int root,int p,int v){
if(l==r){
sum[root]+=v;
return ;
}
int mid=l+r>>1;
if(mid>=p)
update(l,mid,root<<1,p,v);
else
update(mid+1,r,root<<1|1,p,v);
sum[root]=sum[root<<1]+sum[root<<1|1];
}
int query(int l,int r,int root,int ql,int qr){
if(l>=ql&&r<=qr)
return sum[root];
int mid=l+r>>1,ans=0;
if(mid>=ql)
ans=query(l,mid,root<<1,ql,qr);
if(mid<qr)
ans+=query(mid+1,r,root<<1|1,ql,qr);
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&h[i].p,&h[i].x,&h[i].y);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&v[i].p,&v[i].x,&v[i].y);
b[i]=v[i].p;
}
m++;
v[m]={M,0,M};
b[m]=1e6;
sort(b+1,b+1+m);
update(0,M,1,0,1),update(0,M,1,M,1);
for(int i=1;i<=n;i++){
if(h[i].x==0){
h[i].x=1;
h[i].y=upper_bound(b+1,b+1+m,h[i].y)-b-1;
}
else{
h[i].x=lower_bound(b+1,b+1+m,h[i].x)-b;
h[i].y=m-1;
}
//if(h[i].p==0||h[i].p==(int)1e6)continue;
if(h[i].x<=h[i].y)
sta[h[i].x].push_back(h[i].p),en[h[i].y].push_back(h[i].p);
}
sort(v+1,v+1+m);
ll ans=0;
for(int i=1;i<=m;i++){
//if(n==100000&&i==m)break;
for(auto j:sta[i])
update(0,M,1,j,1);
ans+=1ll*query(0,M,1,v[i].x,v[i].y)-1;
for(auto j:en[i])
update(0,M,1,j,-1);
}
printf("%lld\n",ans);
return 0;
}