HDU-1255 覆盖的面积 (线段树 求矩形覆盖面积)

覆盖的面积

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


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 <bits/stdc++.h>
using namespace std;
const int maxn = 1001;
struct Xpoint{
	double x, l, r;
	int v;
	bool operator < (const Xpoint& e){
		return x < e.x;
	}
}line[maxn << 1];
struct tree{
	int cover;
	double len1, len2;
}c[maxn << 4];
double y[maxn << 2];
void build(int o, int l, int r){
	c[o].cover = c[o].len1 = c[o].len2 = 0;
	if(l == r - 1) return;
	int mid = l + r >> 1;
	build(o << 1, l, mid);
	build(o << 1 | 1, mid, r);
}
void pushup(int o, int l, int r){
	if(c[o].cover > 0){
		c[o].len1 = y[r] - y[l];
	}
	else if(l == r - 1){
		c[o].len1 = 0;
	}
	else{
		c[o].len1 = c[o << 1].len1 + c[o << 1 | 1].len1;
	}

	if(c[o].cover > 1){
		c[o].len2 = y[r] - y[l];
	}
	else if(l == r - 1){
		c[o].len2 = 0;
	}
	else if(c[o].cover == 1){
		c[o].len2 = c[o << 1].len1 + c[o << 1 | 1].len1;   //如果当前被完全覆盖了一层,那么不连续的子区间就是第二层覆盖
	}
	else c[o].len2 = c[o << 1].len2 + c[o << 1 | 1].len2;
}
void add(int o, int l, int r, int L, int R, int v){
	if(l >= R || r <= L) return;
	if(l >= L && r <= R){
		c[o].cover += v;
		pushup(o, l, r);
		return;
	}
	int mid = l + r >> 1;
	add(o << 1, l, mid, L, R, v);
	add(o << 1 | 1, mid, r, L, R, v);
	pushup(o, l, r);
}
int main(){
	int n, T;
	scanf("%d", &T);
	double x1, x2, y1, y2;
	while(T--){
		scanf("%d", &n);
		int tot = 0;
		for(int i = 1; i <= n; ++i){
			scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
			line[++tot].x = x1;
			line[tot].l = y1;
			line[tot].r = y2;
			line[tot].v = 1;
			y[tot] = y1;

			line[++tot].x = x2;
			line[tot].l = y1;
			line[tot].r = y2;
			line[tot].v = -1;
			y[tot] = y2;
		}
		build(1, 1, tot);
		sort(y + 1, y + 1 + tot);
		sort(line + 1, line + 1 + tot);
		double ans = 0;
		for(int i = 1; i < tot; ++i){
			y1 = lower_bound(y + 1, y + 1 + tot, line[i].l) - y;
			y2 = lower_bound(y + 1, y + 1 + tot, line[i].r) - y;
			add(1, 1, tot, y1, y2, line[i].v);
			ans += c[1].len2 * (line[i + 1].x - line[i].x);
		}
		printf("%.2lf\n", ans);
	}
}

/*
题意:
1000个矩形,坐标范围1e5,求所有矩形的总覆盖面积。

思路:
我们把y轴映射到线段树上,离散化一下,按照x的坐标从小到大依次处理所有矩形的平行于y轴的边。
每一个矩形x坐标小的边表示后面这个区域是被覆盖的,直到遇到x大的边结束。那么我们对于所有矩形
左边的边,我们讲其加到线段树的区间上,这样每处理一条边,区间上被覆盖的区间长度可以计算出来,
即这一段y轴的区域是被覆盖的,再利用x算一下这一段的面积。一直处理完所有面积即可。
这一题需要主要的是需要维护两次覆盖,计算覆盖区间时需要分类讨论一下。
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值