HDU-1542 Atlantis(离散化+扫描线)
题目大意:给n个矩形,可能重叠,求面积。
题目分析:线段树维护扫描线。
代码如下:
# include<bits/stdc++.h> using namespace std; # define LL long long # define mid (l+(r-l)/2) const int N=100000; struct Segment { double x1,x2,y; bool buttom; }; Segment seg[(N<<1)+5]; struct Node { double m; ///被覆盖的长度 int c; ///被完全覆盖的次数 }; Node tr[N*4+5]; double x[N*2+5]; map<double,int>mp; bool comp(const Segment &s1,const Segment &s2) { return s1.y<s2.y; } void build(int rt,int l,int r) { tr[rt].m=0.0; tr[rt].c=0; if(l==r) return ; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void updateHere(int rt,int l,int r) { if(tr[rt].c>0) tr[rt].m=x[r]-x[l-1]; else if(l==r) tr[rt].m=0; else tr[rt].m=tr[rt<<1].m+tr[rt<<1|1].m; } void update(int rt,int l,int r,int L,int R,int val) { if(L<=l&&r<=R){ tr[rt].c+=val; updateHere(rt,l,r); }else{ if(L<=mid) update(rt<<1,l,mid,L,R,val); if(R>mid) update(rt<<1|1,mid+1,r,L,R,val); updateHere(rt,l,r); } } int main() { int n; int cas=0; while(~scanf("%d",&n)&&n) { double x1,y1,x2,y2; for(int i=0;i<n;++i){ cin>>x1>>y1>>x2>>y2; seg[i<<1].x1=x1,seg[i<<1].x2=x2; seg[i<<1].y=y1; seg[i<<1].buttom=true; seg[i<<1|1].x1=x1,seg[i<<1|1].x2=x2; seg[i<<1|1].y=y2; seg[i<<1|1].buttom=false; x[i<<1]=x1; x[i<<1|1]=x2; } n<<=1; sort(seg,seg+n,comp); sort(x,x+n); int len=unique(x,x+n)-x; for(int i=0;i<len;++i) mp[x[i]]=i; build(1,1,len-1); seg[2*n].y=seg[2*n-1].y; double ans=0; for(int i=0;i<n;++i){ int l=mp[seg[i].x1]; int r=mp[seg[i].x2]; if(seg[i].buttom) update(1,1,len-1,l+1,r,1); else update(1,1,len-1,l+1,r,-1); ans+=tr[1].m*(seg[i+1].y-seg[i].y); } printf("Test case #%d\n",++cas); printf("Total explored area: %.2lf\n\n",ans); } return 0; }