線段樹(掃描線)掃描線求矩形外邊界周長
阿新 • • 發佈:2018-11-22
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=22222; #define lson i*2,l,m #define rson i*2+1,m+1,r int cnt[MAXN*4],suf[MAXN*4],pre[MAXN*4],numseg[MAXN*4],sum[MAXN*4]; struct node { int l,r,h,d; node(){} node(int a,int b,int c,int d):l(a),r(b),h(c),d(d){} bool operator < (const node & b)const { if (h == b.h) return d > b.d;//這句話不寫也AC,但是還是寫上保險,對於本題來說寫不寫沒區別 return h<b.h; } }nodes[MAXN]; void PushUp(int i,int l,int r) { if(cnt[i]) { numseg[i]=2; pre[i]=suf[i]=1; sum[i]=r-l+1; } else if(l==r) numseg[i]=pre[i]=suf[i]=sum[i]=0; else { numseg[i]=numseg[i*2]+numseg[i*2+1]; if(suf[i*2] && pre[i*2+1]) numseg[i]-=2; sum[i]=sum[i*2]+sum[i*2+1]; pre[i]=pre[i*2]; suf[i]=suf[i*2+1]; } } void update(int ql,int qr,int v,int i,int l,int r) { if(ql<=l&&r<=qr) { cnt[i]+=v; PushUp(i,l,r); return ; } int m=l+(r-l)/2;//這裡一定小心,如果是m=(l+r)/2,會無限遞迴,棧溢位,如ql=qr=-1且l=-1,r=0的時候 if(ql<=m) update(ql,qr,v,lson); if(m<qr) update(ql,qr,v,rson); PushUp(i,l,r); } int main() { int t; while(scanf("%d",&t)==1) { int m=0; int lbd=10000,rbd=-10000; for(int i=1;i<=t;i++) { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); lbd=min(lbd,x1); rbd=max(rbd,x2); nodes[++m]= node(x1,x2,y1,1); nodes[++m]= node(x1,x2,y2,-1); } sort(nodes+1,nodes+m+1); int ans=0,last=0;; for(int i=1;i<=m;i++) { int ql=nodes[i].l; int qr=nodes[i].r-1; if(ql<=qr)update(ql,qr,nodes[i].d,1,lbd,rbd-1); ans += abs(last-sum[1]); last=sum[1]; if(i<m) ans+= numseg[1]*(nodes[i+1].h-nodes[i].h); } printf("%d\n",ans); } }