题:https://codeforces.com/contest/1401/problem/E
题意:给定n条横线,m条竖线,问(0,0)到(1e6,1e6)的正方形被分割成几部分,强条件:每个线段与正方形的至少一条边相交,并且没有线段共线。
分析:平行于x轴的线段记左端点贡献为1,右端点+1位置贡献为-1;
以平行于y轴做一条扫描线(从x=0扫到x=1e6),若扫到平行于x轴的线段,则将贡献点加到以y轴为单位的树状数组上,然后统计当前位置存在的平行于y轴的线段产生的贡献。
#include<bits/stdc++.h> using namespace std; #define lson root<<1,l,midd #define rson root<<1|1,midd+1,r #define pb push_back #define ull unsigned long long #define pii pair<int,int> #define MP make_pair typedef long long ll; const ll INF=1e18; const int inf=0x3f3f3f3f; const int M=1e6+6; ll tr[M]; vector<pii >a[M],b[M]; void add(int x,int c){ while(x<=1e6){ tr[x]+=c; x+=x&(-x); } } ll sum(int x){ ll res=0; while(x){ res+=tr[x]; x-=x&(-x); } return res; } int main(){ int n,m; ll ans=1; scanf("%d%d",&n,&m); for(int y,x1,x2,i=1;i<=n;i++){ scanf("%d%d%d",&y,&x1,&x2); a[x1].pb(MP(y,1)); a[x2+1].pb(MP(y,-1)); if(x1==0&&x2==1e6) ans++; } for(int x,y1,y2,i=1;i<=m;i++){ scanf("%d%d%d",&x,&y1,&y2); b[x].pb(MP(y1,y2)); if(y1==0&&y2==1e6) ans++; } for(int i=0;i<=1e6;i++){ for(auto it:a[i]) add(it.first,it.second); for(auto it:b[i]){ ll tmp1=sum(it.second); int l=it.first; ll tmp2; if(l==0) tmp2=0; else tmp2=sum(l-1); ans+=tmp1-tmp2; } } printf("%lld ",ans); return 0; }