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;
}