HDU - 1255 覆盖的面积

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

思路:

类似HDU1542 https://blog.csdn.net/brucehb/article/details/87830077

需要改动的是:

1:当一个子线段原来的flag为1,并且新的flag为1时,记录底边的高度;

2:当一个子线段原来的flag为2,并且新的flag为-1时,计算重叠区域的面积。

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;

typedef long long ll;
const int MAXN = 2005;

double area = 0;
double x[MAXN];

struct Line
{
	double l, r;
	double y;
	int flag;
}line[MAXN];

struct Node
{
	double l, r;
	double y;
	int flag;
	bool end;
}node[MAXN << 2];

bool cmp(const Line &a, const Line &b)
{
	return a.y < b.y;
}

void build(int rt, int l, int r)
{
	node[rt].l = x[l];
	node[rt].r = x[r];
	node[rt].y = 0;
	node[rt].flag = 0;

	if (l + 1 == r)
	{
		node[rt].end = true;
		return;
	}

	node[rt].end = false;
	int mid = l + (r - l) / 2;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid, r);
}

void update(int rt, double l, double r, int flag, double y)
{
	if (l >= node[rt].r || r <= node[rt].l)
	{
		return;
	}

	if (node[rt].end)
	{
		if ((node[rt].flag == 2) && (flag == -1))
		{
			area += (node[rt].r - node[rt].l) * (y - node[rt].y);
		}
		else if ((node[rt].flag == 1) && (flag == 1))
		{
			node[rt].y = y;
		}

		node[rt].flag += flag;
	}
	else
	{
		update(rt << 1, l, r, flag, y);
		update(rt << 1 | 1, l, r, flag, y);
	}
}

int main() 
{
	int m, n;
	double x1, y1, x2, y2;
	int Case = 0;

	scanf("%d", &Case);
	
	while (Case > 0)
	{
		Case--;
		scanf("%d", &n);
		area = 0;
		int count = -1;
		for (int i = 0; i < n; i++)
		{
			scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
			count++;
			x[count] = x1;
			line[count].l = x1;
			line[count].r = x2;
			line[count].y = y1;
			line[count].flag = 1;

			count++;
			x[count] = x2;
			line[count].l = x1;
			line[count].r = x2;
			line[count].y = y2;
			line[count].flag = -1;
		}
		sort(x, x + count + 1);
		sort(line, line + count + 1, cmp);

		build(1, 0, count);

		for (int i = 0; i <= count; i++)
		{
			update(1, line[i].l, line[i].r, line[i].flag, line[i].y);
		}

		printf("%.2lf\n", area);
	}

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值