扫描线,线段树,离散化——HDU - 1542
Posted helman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫描线,线段树,离散化——HDU - 1542相关的知识,希望对你有一定的参考价值。
题目含义
每一行给出两个点,代表一个矩形的左下角端点和右上角端点
要你求出这些矩形覆盖坐标轴的整个面积
题目分析
用平行x轴的扫描线扫描整个图形,得到很多长宽不同的矩形,求出面积再相加
将每个矩形的面积记作 len(x)*len(y)
每个len(x)我们通过加减每个点的x左右坐标,通过线段树求sum[1]得到
每个len(y)我们通过这个点与下一个点的y坐标的差得到
所以我们要把所有点按y轴大小排序,并且记录每个点的左右x轴坐标
注意:这里用的线段树sum【l,r】不是指区间【l,r】的和,而是指X.l和X.r的差
题目代码
#include<stdio.h> #include<iostream> #include<vector> #include<string.h> #include<algorithm> using namespace std; const int maxn=1e5+7; typedef long long LL; vector<double>v; int n; double x1,y1,x2,y2; double len[maxn<<2]; int cov[maxn<<2]; struct node double y,x1,x2; int k; rem[maxn]; int getid(double x) return lower_bound(v.begin(),v.end(),x)-v.begin()+1; bool cmp(node a,node b) return a.y<b.y; void pushup(int l,int r,int rt) if(cov[rt]>0)len[rt]=v[r]-v[l-1]; else if(l==r)len[rt]=0; else len[rt]=len[rt<<1]+len[rt<<1|1]; void updata(int l,int r,int rt,int ll,int rr,int k) if(ll<=l&&r<=rr) cov[rt]+=k; pushup(l,r,rt); return; int mid=(l+r)>>1; if(ll<=mid)updata(l,mid,rt<<1,ll,rr,k); if(rr>mid)updata(mid+1,r,rt<<1|1,ll,rr,k); pushup(l,r,rt); int main() int ce=0; while(scanf("%d",&n)&&n) memset(len,0,sizeof(len)); memset(cov,0,sizeof(cov)); v.clear(); int cnt=0; for(int i=0;i<n;i++) scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); v.push_back(x1); v.push_back(x2); rem[++cnt].x1=x1,rem[cnt].x2=x2,rem[cnt].y=y1,rem[cnt].k=1; rem[++cnt].x1=x1,rem[cnt].x2=x2,rem[cnt].y=y2,rem[cnt].k=-1; sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); sort(rem+1,rem+1+cnt,cmp); double ans=0; for(int i=1;i<cnt;i++) updata(1,cnt,1,getid(rem[i].x1),getid(rem[i].x2)-1,rem[i].k); ans+=len[1]*(rem[i+1].y-rem[i].y); printf("Test case #%d\nTotal explored area: %.2f\n\n",++ce,ans); return 0;
以上是关于扫描线,线段树,离散化——HDU - 1542的主要内容,如果未能解决你的问题,请参考以下文章
hdu1542 Atlantis (线段树+扫描线+离散化)
HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)