HDU-1255-覆盖的面积(线段树)
2014-07-06 20:24
288 查看
[align=left]Problem Description[/align]
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
[align=left]Input[/align]
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
[align=left]Output[/align]
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
[align=left]Sample Input[/align]
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
[align=left]Sample Output[/align]
7.63
0.00
[align=left]Author[/align]
Ignatius.L & weigang Lee
思路:把所有矩形的垂直于y轴的边记录下来再按x坐标从小到大排序,再把y坐标记录下来按从小到大排序,建树的时候把y坐标赋给节点,更新的时候维护区间的重叠次数,然后再求面积 node[1].m*(l[i].x-l[i-1].x) ,i为当前未被放进树里面的边。
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct L{
int val;//1代表是左边的垂直y轴的边,-1代表是右边的垂直y轴的边
double x,y1,y2;
}l[2000];
struct N{
double l,r,o,m;//o为重叠一次的长度,m为重叠多次的长度
int cnt;//记录重叠情况
}node[8000];
double tempy[2000];
bool cmp(struct L a,struct L b)
{
return a.x<b.x;
}
void build(int idx,int s,int e)
{
node[idx].cnt=0;
node[idx].m=0;
node[idx].o=0;
node[idx].l=tempy[s-1];
node[idx].r=tempy[e-1];
if(s+1!=e)
{
int mid=(s+e)>>1;
build(idx<<1,s,mid);
build(idx<<1|1,mid,e);
}
}
void len(int idx,int s,int e)
{
if(node[idx].cnt>=2) node[idx].m=node[idx].r-node[idx].l;//两次以上
else if(node[idx].cnt==1)//一次
{
node[idx].o=node[idx].r-node[idx].l;
if(s+1!=e)
{
node[idx].m=node[idx<<1].o+node[idx<<1|1].o;
}
else node[idx].m=0;
}
else
{
if(s+1!=e)
{
node[idx].m=node[idx<<1].m+node[idx<<1|1].m;
node[idx].o=node[idx<<1].o+node[idx<<1|1].o;
}
else node[idx].m=node[idx].o=0;
}
}
void update(int idx,int s,int e,struct L line)
{
if(node[idx].l==line.y1 && node[idx].r==line.y2)
{
node[idx].cnt+=line.val;
len(idx,s,e);
return;
}
if(s+1!=e)
{
int mid=(s+e)>>1;
if(line.y2<=node[idx<<1].r) update(idx<<1,s,mid,line);
else if(line.y1>=node[idx<<1|1].l) update(idx<<1|1,mid,e,line);
else
{
double temp=line.y2;
line.y2=node[idx<<1].r;
update(idx<<1,s,mid,line);
line.y2=temp;
line.y1=node[idx<<1|1].l;
update(idx<<1|1,mid,e,line);
}
}
len(idx,s,e);
}
int main()
{
int T,n,i;
double x1,x2,y1,y2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
tempy[i*2]=y1;
tempy[i*2+1]=y2;
l[i*2].val=1;
l[i*2].x=x1;
l[i*2].y1=y1;
l[i*2].y2=y2;
l[i*2+1].val=-1;
l[i*2+1].x=x2;
l[i*2+1].y1=y1;
l[i*2+1].y2=y2;
}
sort(tempy,tempy+n*2);
sort(l,l+n*2,cmp);
build(1,1,n*2);
double ans=0;
for(i=0;i<n*2;i++)
{
if(i>1) ans+=node[1].m*(l[i].x-l[i-1].x);
update(1,1,n*2,l[i]);
}
printf("%.2lf\n",ans);
}
}
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
[align=left]Input[/align]
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
[align=left]Output[/align]
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
[align=left]Sample Input[/align]
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
[align=left]Sample Output[/align]
7.63
0.00
[align=left]Author[/align]
Ignatius.L & weigang Lee
思路:把所有矩形的垂直于y轴的边记录下来再按x坐标从小到大排序,再把y坐标记录下来按从小到大排序,建树的时候把y坐标赋给节点,更新的时候维护区间的重叠次数,然后再求面积 node[1].m*(l[i].x-l[i-1].x) ,i为当前未被放进树里面的边。
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct L{
int val;//1代表是左边的垂直y轴的边,-1代表是右边的垂直y轴的边
double x,y1,y2;
}l[2000];
struct N{
double l,r,o,m;//o为重叠一次的长度,m为重叠多次的长度
int cnt;//记录重叠情况
}node[8000];
double tempy[2000];
bool cmp(struct L a,struct L b)
{
return a.x<b.x;
}
void build(int idx,int s,int e)
{
node[idx].cnt=0;
node[idx].m=0;
node[idx].o=0;
node[idx].l=tempy[s-1];
node[idx].r=tempy[e-1];
if(s+1!=e)
{
int mid=(s+e)>>1;
build(idx<<1,s,mid);
build(idx<<1|1,mid,e);
}
}
void len(int idx,int s,int e)
{
if(node[idx].cnt>=2) node[idx].m=node[idx].r-node[idx].l;//两次以上
else if(node[idx].cnt==1)//一次
{
node[idx].o=node[idx].r-node[idx].l;
if(s+1!=e)
{
node[idx].m=node[idx<<1].o+node[idx<<1|1].o;
}
else node[idx].m=0;
}
else
{
if(s+1!=e)
{
node[idx].m=node[idx<<1].m+node[idx<<1|1].m;
node[idx].o=node[idx<<1].o+node[idx<<1|1].o;
}
else node[idx].m=node[idx].o=0;
}
}
void update(int idx,int s,int e,struct L line)
{
if(node[idx].l==line.y1 && node[idx].r==line.y2)
{
node[idx].cnt+=line.val;
len(idx,s,e);
return;
}
if(s+1!=e)
{
int mid=(s+e)>>1;
if(line.y2<=node[idx<<1].r) update(idx<<1,s,mid,line);
else if(line.y1>=node[idx<<1|1].l) update(idx<<1|1,mid,e,line);
else
{
double temp=line.y2;
line.y2=node[idx<<1].r;
update(idx<<1,s,mid,line);
line.y2=temp;
line.y1=node[idx<<1|1].l;
update(idx<<1|1,mid,e,line);
}
}
len(idx,s,e);
}
int main()
{
int T,n,i;
double x1,x2,y1,y2;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
tempy[i*2]=y1;
tempy[i*2+1]=y2;
l[i*2].val=1;
l[i*2].x=x1;
l[i*2].y1=y1;
l[i*2].y2=y2;
l[i*2+1].val=-1;
l[i*2+1].x=x2;
l[i*2+1].y1=y1;
l[i*2+1].y2=y2;
}
sort(tempy,tempy+n*2);
sort(l,l+n*2,cmp);
build(1,1,n*2);
double ans=0;
for(i=0;i<n*2;i++)
{
if(i>1) ans+=node[1].m*(l[i].x-l[i-1].x);
update(1,1,n*2,l[i]);
}
printf("%.2lf\n",ans);
}
}
相关文章推荐
- hdu 1255 覆盖的面积 线段树扫描线num2
- HDU 1255 覆盖的面积 线段树+扫描线
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- HDU 1255 覆盖的面积(离散化+线段树)
- HDU 1255 - 覆盖的面积 (线段树 扫描线 面积交)
- HDU 1255 覆盖的面积(线段树+扫描线求面积【升级版】)
- HDU 1255 覆盖的面积(线段树求矩形面积交)
- 覆盖的面积 HDU - 1255 线段树-扫描线
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- HDU 1255 覆盖的面积(线段树扫描线)
- HDU - 1255 覆盖的面积(线段树 扫描线)
- hdu 1255 覆盖的面积 (线段树处理面积覆盖问题(模板))
- hdu 1255 覆盖的面积 线段树求面积的交 我感觉有点难啊~~第一次写这种类型的
- hdu 1255 覆盖的面积(线段树离散化)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- HDU 1255 覆盖的面积 线段树 扫描线
- HDU-1255-覆盖的面积-线段树求面积并(模板)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- 【线段树 && 扫描线 && 面积交】HDU - 1255 覆盖的面积