注意点:
- 线段树中使用获取具体长度时右端点应当+1,向线段树内插入值时右端点应当-1.(区间覆盖线段树)
#include<cstdio> #include<iostream> #include<algorithm> #define ll long long using namespace std; const int MAXN=2e6; struct Line{ ll x1,x2,y; bool type; bool operator <(Line another)const{ return y<another.y; } }lines[MAXN]; int lineCnt=0; struct Node{ int l,r; ll len,cnt; }tr[MAXN]; void build(int p,int l,int r){ tr[p].l=l,tr[p].r=r; if(l==r)return; int mid=(l+r)>>1; build(p<<1,l,mid); build((p<<1)|1,mid+1,r); } ll a[MAXN];//离散化 void pushup(int p){ if(tr[p].cnt){ tr[p].len=a[tr[p].r+1]-a[tr[p].l]; }else{ tr[p].len=tr[p<<1].len+tr[(p<<1)|1].len; } } void change(int p,int l,int r,int val){ if(tr[p].l>=l&&tr[p].r<=r){ tr[p].cnt+=val; pushup(p); return; } int mid=(tr[p].l+tr[p].r)>>1; if(l<=mid)change(p<<1,l,r,val); if(r>mid)change((p<<1)|1,l,r,val); pushup(p); } int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ ll x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; lines[++lineCnt].x1=x1,lines[lineCnt].x2=x2; lines[lineCnt].y=y1,lines[lineCnt].type=0; lines[++lineCnt].x1=x1,lines[lineCnt].x2=x2; lines[lineCnt].y=y2,lines[lineCnt].type=1; a[i]=x1,a[i+n]=x2; } sort(a+1,a+2*n+1); int cnt=unique(a+1,a+2*n+1)-a-1;//离散化 sort(lines+1,lines+2*n+1); build(1,1,cnt-1); ll ans=0; for(int i=1;i<=2*n;i++){ Line nowLine=lines[i]; if(i>1)ans+=tr[1].len*(lines[i].y-lines[i-1].y); if(nowLine.type){//消失 change(1,lower_bound(a+1,a+cnt+1,nowLine.x1)-a,lower_bound(a+1,a+cnt+1,nowLine.x2)-a-1,-1); }else{//出现 change(1,lower_bound(a+1,a+cnt+1,nowLine.x1)-a,lower_bound(a+1,a+cnt+1,nowLine.x2)-a-1,1); } } cout<<ans<<endl; return 0; }