Luogu5490 【模板】掃描線
阿新 • • 發佈:2020-08-04
https://www.luogu.com.cn/problem/P5490
掃描線
根據橫座標或縱座標排序另一方向的線段,進入的賦值\(+1\),離開的賦值\(-1\)
注意一下,線段樹的構造中,一個位置表示的是一個間隔,即\(a_1\)表示間隔\([1,2]\),間隔個數為點的個數\(-1\)
如果用點來建,一個點根本無法計算貢獻
\(C++ Code:\)
#include<iostream> #include<cstdio> #include<algorithm> #define ll long long #define N 200005 using namespace std; int x,y,_x,_y,n,cnt,cc; int a1[N],a2[N],b1[N],b2[N],c[N]; ll ans; struct node { int x,y,_y,t; bool operator < (const node b) const { return x<b.x; } }w[N]; struct T { int cnt,len; }t[N << 2]; void push_up(int p,int l,int r) { if (t[p].cnt) t[p].len=c[r+1]-c[l]; else if (l!=r) t[p].len=t[p+p].len+t[p+p+1].len; else t[p].len=0; } void add(int p,int l,int r,int x,int y,int z) { if (l>y || r<x) return; if (x<=l && r<=y) { t[p].cnt+=z; push_up(p,l,r); return; } int mid=(l+r) >> 1; add(p+p,l,mid,x,y,z); add(p+p+1,mid+1,r,x,y,z); push_up(p,l,r); } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d%d%d%d",&x,&y,&_x,&_y); w[i+i-1].x=x; w[i+i-1].y=y; w[i+i-1]._y=_y; w[i+i-1].t=1; w[i+i].x=_x; w[i+i].y=y; w[i+i]._y=_y; w[i+i].t=-1; c[i+i-1]=_y,c[i+i]=y; } cnt=n << 1; sort(c+1,c+cnt+1); cc=unique(c+1,c+cnt+1)-c-1; sort(w+1,w+cnt+1); for (int i=1;i<=cnt;i++) { w[i].y=lower_bound(c+1,c+cc+1,w[i].y)-c; w[i]._y=lower_bound(c+1,c+cc+1,w[i]._y)-c; } for (int i=1;i<cnt;i++) { add(1,1,cc,w[i].y,w[i]._y-1,w[i].t); ans+=(ll)t[1].len*(w[i+1].x-w[i].x); } printf("%lld\n",ans); return 0; }