您的位置:首页 > 其它

Hdu 1255 覆盖的面积 线段树+矩形面积并

2013-08-27 13:40 495 查看
继续面积并学习中。。。(线段树解决)

题意:给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积

思路:其实跟求矩形面积并的思想是一样的,只不过在update里做了一点修改,矩形面积并只需要求至少覆盖一次的面积,而这题是至少覆盖两次的面积,稍微做点修改就可以了

一样的,要求面积,就要求出至少覆盖两次的有效长度乘以高度差即可,求有效长度:

1.cnt>1 : 说明该区间被覆盖两次或以上,那么长度就可以直接计算,就是该区间的长度

剩下的情况就是cnt=1或cnt=0

2.先看叶子节点,因为是叶子没有孩子了,所以被覆盖两次货以上的长度就是0(无论cnt=1或cnt=0都是0,因为是叶子。。。)

3.不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,应该是,可以确定,这个区间被完全覆盖了1次,而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,只要加上sum1[左孩子]+sum1[右孩子] 即看看左右孩子区间被覆盖了一次或以上的长度,那么叠加在双亲上就是双亲被覆盖两次或以上的长度

4.不是叶子节点,且cnt=0,确切的意义应该是不完全不知道被覆盖的情况(不知道有没有被覆盖,被覆盖了几次,长度是多少都不知道),这种情况,只能由其左右孩子的信息所得

sum2[左孩子]+sum2[右孩子] , 即直接将左右孩子给覆盖了两次或以上的长度加起来,这样才能做到不重不漏

这里:我用sum1代表至少被覆盖一次的有效长度,sum2代表至少覆盖两次的有效长度

代码:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
using namespace std;
const int M=2010;
double sum1[M<<2],sum2[M<<2];
int cnt[M<<2];
double x[M];
struct node
{
double  l,r,h;
int flag;
node() {}
node(double x1,double x2,double y,int s) :l(x1),r(x2),h(y),flag(s) {}
bool operator <(const node& rsh)const
{
return h<rsh.h;
}
} line[M];
int Bin(double key,int n,double x[])
{
int l=0,r=n-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(x[mid]==key)return mid;
else if(x[mid]<key)l=mid+1;
else
r=mid-1;
}
return -1;
}
//void build(int l,int r,int num)
//{
//    sum1[num]=sum2[num]=cnt[num]=0;
//    if(l==r)
//    return;
//    int mid=(l+r)>>1;
//    build(lson);
//    build(rson);
//}
void PushUp(int num,int l,int r)
{

if(cnt[num]) sum1[num] = x[r+1]-x[l];
else if(l==r)sum1[num]=0;//判断叶子结点,只要是叶子结点就都为0
else
sum1[num]=sum1[num<<1]+sum1[num<<1|1];

if(cnt[num]>1)sum2[num]=x[r+1]-x[l];
else if(l==r)sum2[num]=0;//判断叶子结点,只要是叶子结点就都为0
else if(cnt[num]==1)
sum2[num]=sum1[num<<1]+sum1[num<<1|1];
else
sum2[num]=sum2[num<<1]+sum2[num<<1|1];

}
void update(int L,int R,int flag,int l,int r,int num)
{
if(L<=l && r<=R)
{
cnt[num]+=flag;
PushUp(num,l,r);
return;
}
int mid=(l+r)>>1;
if(L<=mid)update(L,R,flag,lson);
if(R>mid)update(L,R,flag,rson);
PushUp(num,l,r);
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
double x1,x2,y2,y1;
scanf("%d",&n);
int st=0;
while(n--)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
x[st]=x1;
line[st++]=node(x1,x2,y1,1);
x[st]=x2;
line[st++]=node(x1,x2,y2,-1);
}
sort(x,x+st);
sort(line,line+st);
int k=1;
for(int i=1; i<st; i++)
{
if(x[i]!=x[i-1])x[k++]=x[i];
}
//build(0,k-1,1);
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
memset(cnt,0,sizeof(cnt));
double ret=0;
for(int i=0; i<st-1; i++)
{
int lx=Bin(line[i].l,k,x);
int rx=Bin(line[i].r,k,x)-1;
if(lx<=rx)update(lx,rx,line[i].flag,0,k-1,1);
ret+=sum2[1]*(line[i+1].h-line[i].h);
}
printf("%.2lf\n",ret);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: