Atlantis POJ-1151——線段樹+掃描線+坐標離散化
阿新 • • 發佈:2019-05-16
mem scan http 線段樹 掃描 mar har rec 矩形
題目鏈接:
http://poj.org/problem?id=1151
題意:
求矩形並集的面積。
思路:
想象一條豎線從最左邊掃描到最右邊,豎線上被矩形覆蓋的地方可以確定,即可計算出被覆蓋長度。
用線段樹維護豎線上被覆蓋的長度。
代碼:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100; struct Rec { double x1,y1,x2,y2; }; struct Line { bool operator<(const Line &t)const{return x<t.x;} double x; int y1,y2,c; }; int n,cy,cl; double y[maxn*2]; Rec rec[maxn]; Line line[maxn*2]; int dat[maxn*2*4]; double sum[maxn*2*4]; void change(int c,int a,int b,int k,int l,int r) { if(a<=l&&b>=r) { dat[k]+=c; if(dat[k]==0) { if(r-l==1) sum[k]=0; else sum[k]=sum[2*k+1]+sum[2*k+2]; } else sum[k]=y[r]-y[l]; } else { int m=(l+r)>>1; if(a<m)change(c,a,b,2*k+1,l,m); if(b>m)change(c,a,b,2*k+2,m,r); if(dat[k]==0) sum[k]=sum[2*k+1]+sum[2*k+2]; } } void discrete()//離散化 { sort(y,y+cy); cy=unique(y,y+cy)-y; } int main() { int k=0; while(scanf("%d",&n)&&n) { cy=0; for(int i=0;i<n;++i) { scanf("%lf%lf%lf%lf",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2); y[cy++]=rec[i].y1; y[cy++]=rec[i].y2; } discrete(); cl=0; for(int i=0;i<n;++i) { line[cl].x=rec[i].x1; line[cl].y1=lower_bound(y,y+cy,rec[i].y1)-y; line[cl].y2=lower_bound(y,y+cy,rec[i].y2)-y;; line[cl++].c=1; line[cl].x=rec[i].x2; line[cl].y1=lower_bound(y,y+cy,rec[i].y1)-y; line[cl].y2=lower_bound(y,y+cy,rec[i].y2)-y;; line[cl++].c=-1; } sort(line,line+cl); memset(dat,0,sizeof(dat)); memset(sum,0,sizeof(sum)); double ans=0; change(line[0].c,line[0].y1,line[0].y2,0,0,cy); double pre=line[0].x; for(int i=1;i<cl;++i) { ans+=(line[i].x-pre)*sum[0]; change(line[i].c,line[i].y1,line[i].y2,0,0,cy); pre=line[i].x; } printf("Test case #%d\nTotal explored area: %.2f\n\n",++k,ans); } return 0; }
Atlantis POJ-1151——線段樹+掃描線+坐標離散化