hdu 1255 覆盖的面积 线段树求面积的交 我感觉有点难啊~~第一次写这种类型的

154 篇文章 1 订阅
8 篇文章 0 订阅

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3968    Accepted Submission(s): 1967


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
 
上博客吧~~我是没能力讲解啊~
http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html
代码:
#include <cstdio>
#include <algorithm>

using namespace std ;

double y[2010] ;

struct Line{
	double x,y_up,y_down ;
	int mark;
}line[2010];

struct node{
	double x;
	double y_up,y_down;
	double cover;
	bool isLeaf ;
}st[400100];

void build(int l , int r , int pos)
{
	st[pos].x = -1   ;
	st[pos].y_down = y[l] ;
	st[pos].y_up = y[r] ;
	st[pos].cover = 0 ;
	st[pos].isLeaf = false ;
	if(l+1 == r)
	{
		st[pos].isLeaf = true ;
		return ;
	}
	int mid = (l+r)>>1 ;
	build(l,mid,pos<<1) ;
	build(mid,r,pos<<1|1) ;
}

double insert(double x , double y_down , double y_up , int mark , int pos)
{
	if(st[pos].y_down>=y_up || st[pos].y_up<=y_down)
	{
		return 0 ;
	}
	if(st[pos].isLeaf)
	{
		if(st[pos].cover>1)
		{
			double tempx = st[pos].x ;
			double area = (x-tempx)*(st[pos].y_up-st[pos].y_down) ;
			st[pos].x = x ;
			st[pos].cover += mark ;
			return area ;
		}
		else
		{
			st[pos].cover += mark ;
			st[pos].x = x ;
			return 0 ;
		}
	}
	return insert(x,y_down,y_up,mark,pos<<1)+insert(x,y_down,y_up,mark,pos<<1|1) ;
}
bool cmp(const Line &a , const Line &b)
{
	return a.x<b.x ;
}
int main()
{
	int t ;
	scanf("%d",&t) ;
	while(t--)
	{
		int n ;
		scanf("%d",&n) ;
		int index = 0 ;
		for(int i = 0 ; i < n ; ++i)
		{
			double x1 , x2 , y1 , y2 ;
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2) ;
			line[index].x = x1 ;
			line[index].y_down = y1 ;
			y[index] = y1 ;
			line[index].y_up = y2 ;
			line[index++].mark = 1 ;
			line[index].x = x2 ;
			line[index].y_down = y1 ;
			line[index].y_up = y2 ;
			y[index] = y2 ;
			line[index++].mark = -1 ;
		}
		sort(line,line+index,cmp);
		sort(y,y+index) ;
		build(0,index-1,1) ;
		double s = 0.0 ;
		for(int i = 0 ; i < index ; ++i)
		{
			s += insert(line[i].x,line[i].y_down,line[i].y_up,line[i].mark,1) ;
		}
		printf("%.2lf\n",s) ;
	}
	return 0 ;
}

与君共勉
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值