http://acm.hdu.edu.cn/showproblem.php?pid=1542
Atlantis
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6788 Accepted Submission(s): 2970
The input file is terminated by a line containing a single 0. Don’t process it.
Output a blank line after each test case.
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,int val)
{
xl=a;xr=b;y=h;v=val;
}
bool operator < (const EDGE &e)const
{
return y<e.y;
}
}edge[maxn];
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;
}