标签:targe 扫描线 tps acm opera efi type stream 矩形
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542
题意:二维平面有n个平行于坐标轴的的矩形,要算矩形面积并
有一个讲的很好的博客:https://blog.csdn.net/u013480600/article/details/22548393
线段树是按叶节点来一个个维护的,一堆浮点数是不能直接维护的,需要离散化来维护。
要注意我们线段树中每个叶节点(控制区间[L,L])不是指X[L]坐标,而是指区间[X[L],X[L+1]].线段树中其他节点控制的区间[L,R],也是指的x坐标轴的第L个区间到第R个区间的范围,也就是X[L]到X[R+1]坐标的范围.
简而言之,维护的是区间。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid (l+r)/2 using namespace std; typedef long long ll; const int maxn=1000+10; double dat[4*maxn]; int lazy[maxn]; double b[maxn]; struct edge{ double l,r,h; int cnt; friend bool operator < (edge x,edge y){ return x.h<y.h; } }e[maxn]; void pushup(int a,int l,int r){ if(lazy[a]) dat[a]=b[r+1]-b[l]; else dat[a]=dat[a<<1]+dat[a<<1|1]; } void update(int a,int l,int r,int s,int t,int k){ if(s>r || t<l) return; if(s<=l && r<=t){ lazy[a]+=k; pushup(a,l,r); return; } if(s<=mid) update(a<<1,l,mid,s,t,k); if(t>mid) update(a<<1|1,mid+1,r,s,t,k); pushup(a,l,r); } int main(){ int n; int T=0; while(~scanf("%d",&n)){ memset(dat,0,sizeof(dat)); memset(lazy,0,sizeof(lazy)); memset(b,0,sizeof(b)); memset(e,0,sizeof(e)); if(n==0) return 0; T++; int p=0,num=0; for(int i=1;i<=n;i++){ double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); e[++p].l=x1; e[p].r=x2; e[p].h=y1; e[p].cnt=1; e[++p].l=x1; e[p].r=x2; e[p].h=y2; e[p].cnt=-1; b[++num]=x1; b[++num]=x2; } sort(e+1,e+1+p); sort(b+1,b+1+num); int m=unique(b+1,b+1+num)-b-1; double ans=0; for(int i=1;i<p;i++){ int l=lower_bound(b+1,b+m,e[i].l)-b; int r=lower_bound(b+1,b+m,e[i].r)-b; update(1,1,m-1,l,r-1,e[i].cnt);//记住r-1是关键,维护的是区间,一共有m-1个区间 ans+=dat[1]*(e[i+1].h-e[i].h); } printf("Test case #%d\n",T); printf("Total explored area: %.2lf\n\n",ans); } return 0; }
标签:targe 扫描线 tps acm opera efi type stream 矩形
原文地址:https://www.cnblogs.com/qingjiuling/p/11330889.html