题意:求\(n(n<=10^5)\)个矩形的面积并.一个矩形的左下角坐标为 \((x_1, y_1)\),右上角坐标为 \((x_2, y_2)\)\((0<=x_1,x_2,y_1,y_2<=1e9)\).
也不晓得为啥,写扫描线的话,数组反正要开离奇地大,然后一定要开long long.反正我一直把数组加大,加着加着就过了.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline ll read(){
ll x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=1e6+5;//离奇地大 就行
ll a[N],raw[N];//全部开long long
struct line{ll x,y1,y2,k;}e[N];
struct xd_tree{ll len,cnt;}t[N<<1];
inline bool cmp(const line &x,const line &y){
return x.x==y.x?x.y1<y.y1:x.x<y.x;
}
inline void pushup(ll p,ll l,ll r){
if(t[p].cnt>0)t[p].len=raw[r+1]-raw[l];
else t[p].len=t[p<<1].len+t[p<<1|1].len;
}
inline void change(ll p,ll l,ll r,ll ql,ll qr,ll val){
if(ql<=l&&r<=qr){
t[p].cnt+=val;
pushup(p,l,r);
return;
}
ll mid=(l+r)>>1;
if(ql<=mid)change(p<<1,l,mid,ql,qr,val);
if(qr>mid)change(p<<1|1,mid+1,r,ql,qr,val);
pushup(p,l,r);
}
int main(){
ll n=read(),tot=0;
for(ll i=1;i<=n;++i){
ll x1=read(),y1=read(),x2=read(),y2=read();
e[(i<<1)-1].x=x1;e[(i<<1)-1].y1=y1;e[(i<<1)-1].y2=y2;e[(i<<1)-1].k=1;
e[i<<1].x=x2;e[i<<1].y1=y1;e[i<<1].y2=y2;e[i<<1].k=-1;
a[++tot]=y1;a[++tot]=y2;//离散化用的数组
}
sort(a+1,a+tot+1);
ll sum=unique(a+1,a+tot+1)-a-1;
n<<=1;
for(int i=1;i<=n;++i){
ll pos1=lower_bound(a+1,a+sum+1,e[i].y1)-a;
ll pos2=lower_bound(a+1,a+sum+1,e[i].y2)-a;
raw[pos1]=e[i].y1;raw[pos2]=e[i].y2;//映射
e[i].y1=pos1;e[i].y2=pos2;
}
sort(e+1,e+n+1,cmp);//按照横坐标从小到大排序
ll ans=0;
for(int i=1;i<=n;++i){
change(1,1,n,e[i].y1,e[i].y2-1,e[i].k);//线段树
ans+=1ll*t[1].len*(e[i+1].x-e[i].x);//统计答案:长乘宽
}
printf("%lld\n",ans);
return 0;
}