码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1255 覆盖的面积(线段树扫描线求面积的交)

时间:2015-03-30 13:26:00      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:线段树

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

技术分享

 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.
 

Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
 

Sample Input
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
 

Sample Output
7.63 0.00







#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)

#define eps 1e-8
#define ll long long

#define fre(i,a,b)  for(i = a; i <b; i++)
#define free(i,b,a) for(i = b; i >= a;i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define ssf(n)      scanf("%s", n)
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define bug         pf("Hi\n")

using namespace std;

#define INF 0x3f3f3f3f

#define N 10005

struct stud{
 double x1,x2,h;
 int type;
 bool operator <(const stud b) const
 {
 	return h<b.h;
 }
}e[N];

struct studd{
  int le,ri;
  int cover;
  double once,len;
}f[N];

map<double,int>mp;

double x[N];

void build(int pos,int le,int ri)
{
	f[pos].le=le;
	f[pos].ri=ri;
	f[pos].cover=0;
	f[pos].once=f[pos].len=0;
	if(le+1==ri) return ;

	int mid=MID(le,ri);
	build(L(pos),le,mid);
	build(R(pos),mid,ri);
}

void pushup(int pos)
{
    if(f[pos].cover>=2)
	{
		f[pos].len=x[f[pos].ri]-x[f[pos].le];
		f[pos].once=0;
		return ;
	}

    if(f[pos].cover==1)   //这个区间被覆盖一次,那么两次的应该是下面的两次的加下面的一次的
	{
		if(f[pos].le+1==f[pos].ri)
		{
			f[pos].len=0;
			f[pos].once=x[f[pos].ri]-x[f[pos].le];
		}
        else
		{
			f[pos].len=f[L(pos)].len+f[L(pos)].once+f[R(pos)].len+f[R(pos)].once;
			f[pos].once=x[f[pos].ri]-x[f[pos].le]-f[pos].len;
		}
       return ;
	}

    if(f[pos].le+1==f[pos].ri)
	{
		f[pos].len=f[pos].once=0;
	}
    else
	{
		f[pos].len=f[L(pos)].len+f[R(pos)].len;
		f[pos].once=f[L(pos)].once+f[R(pos)].once;
	}

}

void update(int pos,int le,int ri,int type)
{
	if(f[pos].le>=le&&f[pos].ri<=ri)
	{
		f[pos].cover+=type;
		pushup(pos);
		return ;
	}
    int mid=MID(f[pos].le,f[pos].ri);

    if(mid>le)
		update(L(pos),le,ri,type);

	if(mid<ri)
		update(R(pos),le,ri,type);

	pushup(pos);
}

int main()
{
   int i,j,n,k,t;
   double x1,x2,y1,y2;

   sf(t);
   while(t--)
   {
   	 sf(n);
   	 k=0;
   	 fre(i,0,n)
   	 {
   	 	 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
   	 	 if(x1>x2) swap(x1,x2);

   	 	 x[k]=x1;
   	 	 e[k].x1=x1;
   	 	 e[k].x2=x2;
   	 	 e[k].h=y1;
   	 	 e[k++].type=1;

   	 	 x[k]=x2;
   	 	 e[k].x1=x1;
   	 	 e[k].x2=x2;
   	 	 e[k].h=y2;
   	 	 e[k++].type=-1;
   	 }

   	 sort(x,x+k);
   	 sort(e,e+k);
   	 n=unique(x,x+k)-x;

   	 fre(i,0,n)
   	   mp[x[i]]=i;

   	 n--;

   	 build(1,0,n);

   	 double ans=0;

   	 fre(i,0,k-1)
   	 {
   	 	int le=mp[e[i].x1];
   	 	int ri=mp[e[i].x2];
   	 	update(1,le,ri,e[i].type);
   	 	ans+=f[1].len*(e[i+1].h-e[i].h);
   	 }
    pf("%.2f\n",ans);
   }
   return 0;
}


HDU 1255 覆盖的面积(线段树扫描线求面积的交)

标签:线段树

原文地址:http://blog.csdn.net/u014737310/article/details/44748605

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!