您的位置:首页 > 其它

hdu 1542 Atlantis 线段树矩形面积并+离散化

2016-02-23 10:48 316 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1542

题意:给一些矩形,可能会有重叠,求总的矩形面积

我是看了胡浩的那篇文章,学习一下。

思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用cnt表示该区间下边比上边多几个,sum代表该区间内被覆盖的线段的长度总和

这里线段树的一个结点并非是线段的一个端点,而是该端点和下一个端点间的线段,所以题目中r+1,r-1的地方可以自己好好的琢磨一下

线段树操作:update:区间增减 query:直接取根节点的值

分析:因为线段树每个节点表示的是一个边长,而不是一些点的区间,比如说对于下边【0,1】区间和上边【1,2】区间,如果在更新的时候r不减1,那么1这个点就会被合并,变成【0,0】和【2,2】的边长和,所以在更新的时候r-1.这样的话在求边长总和sum的时候再把1加上去,这样就解决这个问题了。如果读不懂,可以看一下这个图上的解释,在理解一下。http://blog.csdn.net/cen5bin/article/details/7833089

离散化横坐标,对横坐标建树,由于在计算横坐标的时候会去重,得到不同的横坐标k个,因为横坐标数组从0开始,所以要k-1。在更新节点的时候,由于r-1,所以也要对应k-1

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=205;
int cnt[N<<2];
double sum[N<<2],X
;
struct edge
{
double l,r,h;
int s;
edge(){}
edge(double a,double b,double c,int d):l(a),r(b),h(c),s(d){}
bool operator<(const edge &cmp)const{
return h<cmp.h;
}
}e
;
void pushUP(int l,int r,int rt)
{
if(cnt[rt])sum[rt]=X[r+1]-X[l];  //如果是整段都有边,总边长直接左右两个端点之差,这里r+1,是因为在更新的时候r减了1
else if(l==r)sum[rt]=0; //如果两个端点没有覆盖边,那么这个边长不加了总长里。
else sum[rt]=sum[rt<<1]+sum[rt<<1|1]; //否则从子节点得到边长
}
void update(int a,int b,int c,int l,int r,int rt)
{
if(a<=l&&r<=b){
cnt[rt]+=c;
pushUP(l,r,rt);
return;
}
int m=(l+r)>>1;
if(a<=m)update(a,b,c,lson);
if(m<b)update(a,b,c,rson);
pushUP(l,r,rt);
}
int Bin(double key,int n,double X[])
{
int l=0,r=n;
while(l<=r){
int m=(l+r)>>1;
if(X[m]==key)return m;
if(X[m]<key)l=m+1;
else r=m-1;
}
return -1;
}
int main()
{
int n,cas=0;
//freopen("f.txt","r",stdin);
while(~scanf("%d",&n)&&n){
int m=0;
while(n--){
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
X[m]=a;
e[m++]=edge(a,c,b,1);
X[m]=c;
e[m++]=edge(a,c,d,-1);
}
sort(X,X+m);
sort(e,e+m);
int k=1;
for(int i=1;i<m;i++){
if(X[i]!=X[i-1])X[k++]=X[i];
}
k--;  //注意这里
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
double ans=0;
for(int i=0;i<m-1;i++){
int l=Bin(e[i].l,k,X);
int r=Bin(e[i].r,k,X)-1;
if(l<=r)update(l,r,e[i].s,0,k-1,1); //k和r都减一的原因是一样的。
ans+=sum[1]*(e[i+1].h-e[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas , ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: