http://acm.hdu.edu.cn/showproblem.php?pid=1542
2 10 10 20 20 15 15 25 25.5 0
Test case #1 Total explored area: 180.00
题意:
给出N个矩形,边与坐标轴平行,问最后组成图形的面积
分析:
线段树扫描线。
因为坐标是浮点数,而且有点大,所以先要离散化,我是用平行于X轴的线从下往上扫的,所以只需要离散化X坐标;前几天多校某一题的标程给了一个离散化的好方法:使用sort() & unique(),我之前都是用map(红黑树);
扫描线要怎么扫呢?首先要把矩形平行于X轴的边分出来,分为下边(1)和上边(-1),并且记录高度(y),然后以高度升序排列;然后就开始扫,遇到下边对应线段+1,上边就-1,这样大于0的区间就对应有线段,每次扫描就计算出对应的面积,求和即可。
维护左闭右开区间的优势显现出来了,哈哈哈哈哈哈哈。。。。
如上图加入第一根线
如上图计算出蓝色面积
如上图加入第二根线
如上图计算绿色部分面积
如上图加入第三根线
如上图计算紫色部分面积
如上图加入最后一根线(that‘s all)
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<ctime> #include<cctype> #include<cmath> #include<string> #include<cstring> #include<stack> #include<queue> #include<list> #include<vector> #include<map> #include<set> #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #define maxm #define maxn 202 using namespace std; struct EDGE { double xl,xr,y; int v; void _set(double a,double b,double h,double val) { xl=a;xr=b;y=h;v=val; } bool operator < (const EDGE &e)const { return y<e.y; } }edge[202]; double X[maxn]; double sum[maxn<<2]; int val[maxn<<2]; inline void pushup(int k,int l,int r) { if (val[k]) sum[k]=X[r]-X[l]; else if (r-l==1) sum[k]=0; else sum[k]=sum[k*2+1]+sum[k*2+2]; } void update(int a,int b,int v,int k,int l,int r) { if (b<=l || r<=a) return ; if (a<=l && r<=b) { val[k]+=v; pushup(k,l,r); } else { update(a,b,v,k*2+1,l,l+r>>1); update(a,b,v,k*2+2,l+r>>1,r); pushup(k,l,r); } } int main() { #ifndef ONLINE_JUDGE freopen("/home/fcbruce/文档/code/t","r",stdin); #endif // ONLINE_JUDGE int n; double x1,x2,y1,y2; int m=202; int T_T=0; while (scanf("%d",&n),n) { for (int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); edge[i]._set(x1,x2,y1,1); edge[i+n]._set(x1,x2,y2,-1); X[i]=x1;X[i+n]=x2; } n<<=1; sort(edge,edge+n); sort(X,X+n); int xn=unique(X,X+n)-X; double area=0; for (int i=0;i<n;i++) { if (i) area+=(edge[i].y-edge[i-1].y)*sum[0]; int a=lower_bound(X,X+xn,edge[i].xl)-X; int b=lower_bound(X,X+xn,edge[i].xr)-X; int v=edge[i].v; update(a,b,v,0,0,m); } T_T++; printf("Test case #%d\n",T_T); printf("Total explored area: %.2f\n\n",area); } return 0; }
HDU 1542 Atlantis(线段树扫描线),布布扣,bubuko.com
原文地址:http://blog.csdn.net/u012965890/article/details/38357545