标签:UI blog math 清空 ons print cal ant pac
2 10 10 20 20 15 15 25 25.5 0Sample Output
Test case #1 Total explored area: 180.00
就是给定你2若干个矩形,求覆盖的面积。
看数据范围,就要用离散化来做,我们可以使用扫描线,沿着x轴扫过去,将每一个x坐标所对应的y的上下界用线段树表示出来,当一个矩形入边加入的时候就+1,否则就-1,然后算出面积就可以了。
具体看代码,我写了一些较为详细的注释。
#pragma GCC optimize("O2")
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<ctype.h>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+(r-l)/2)
#define maxn 500
#define LL long long
using namespace std;
struct TREE{int l,r,c;double cnt,lf,rf;}tr[maxn*4];//l,r存线段树的下标,c存+1-1,就是这颗扫描线扫过的矩形的数量,cnt存答案,也就是一段区间,lf,rf为区间的左右界
struct Line{double x,y1,y2;int c;}line[maxn];
int m=0,n;
double y[maxn];
bool cmp(Line a,Line b){return a.x<b.x;}
void build(int l,int r,int rt)//离散化,坐标一一对应
{
tr[rt].l=l;tr[rt].r=r;
tr[rt].cnt=tr[rt].c=0;
tr[rt].lf=y[l],tr[rt].rf=y[r];
if(l+1==r) return;//左闭右开的区间
build(l,mid,ls);
build(mid,r,rs);//同上所以不是mid+1
}//说一下区间为什么要 左闭右开,因为这样在计算面积的时候就不用+1-1,就不会出现细节上的错误
void getlen(int rt)
{
if(tr[rt].c)
{
tr[rt].cnt=tr[rt].rf-tr[rt].lf;
// tr[rt].c=0;//注意这里不能清空,应该在下一条出边加入的时候才能清空
return ;
}
if(tr[rt].l+1==tr[rt].r) tr[rt].cnt=0;//如果是一个节点而不是区间
else tr[rt].cnt=tr[ls].cnt+tr[rs].cnt;
return ;
}
void update(int rt,Line e)
{
if(e.y1==tr[rt].lf&&e.y2==tr[rt].rf)
{
tr[rt].c+=e.c;
getlen(rt);
return ;
}
if(e.y2<=tr[ls].rf) update(ls,e);//左儿子和右儿子要分开计算
else if(e.y1>=tr[rs].lf) update(rs,e);
else
{
Line tmp=e;
tmp.y2=tr[ls].rf; update(ls,tmp);
tmp=e;
tmp.y1=tr[rs].lf; update(rs,tmp);
}
getlen(rt);
}
void input()
{
double x1,x2,y1,y2;
for(int i=1;i<=n;i++)
{
cin>>x1>>y1>>x2>>y2;
line[++m].x=x1;line[m].y1=y1;line[m].y2=y2;line[m].c=1;
y[m]=y1;
line[++m].x=x2;line[m].y1=y1;line[m].y2=y2;line[m].c=-1;
y[m]=y2;
}
sort(line+1,line+m+1,cmp);
sort(y+1,y+m+1);//坐标离散化
}
void init()//记得初始化
{
memset(tr,0,sizeof(tr));
m=0;
memset(line,0,sizeof(line));
memset(y,0,sizeof(y));
}
int main()
{
int kase=0;
while(cin>>n&&n)
{
init();
input();
build(1,m,1);
update(1,line[1]);//先加入第一条线
double ans=0;
for(int i=2;i<=m;i++)
{
ans+=tr[1].cnt*(line[i].x-line[i-1].x);//标准的面积计算公式
update(1,line[i]);
}
printf("Test case #%d\n", ++kase);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}
/*
2
1 1 3 3
2 2 4 4
*/
标签:UI blog math 清空 ons print cal ant pac
原文地址:http://www.cnblogs.com/foreverpiano/p/7073112.html