给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
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 1Sample Output
7.63 0.00
思路 :
唯一区别于 矩形的面积并的地方 就是他所要的下边是被两次重复覆盖的边 。
代码示例 :
/*
* Author: ry
* Created Time: 2017/10/24 8:57:44
* File Name: 1.cpp
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <time.h>
using namespace std;
const int eps = 3e+5;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define ll long long
struct seg
{
double l, r, h;
int f;
}po[eps];
double x[eps];
bool cmp(seg a, seg b){
return a.h < b.h;
}
struct node
{
int l, r, sum;
double len1, len2;
}pre[eps<<2];
void build(int l, int r, int k){
pre[k].l = l;
pre[k].r = r;
pre[k].sum = pre[k].len1 = pre[k].len2 = 0;
if (l == r) return;
int m = (l+r)>>1;
build(l, m, k<<1);
build(m+1, r, k<<1|1);
}
void down(int k){
if (pre[k].sum) pre[k].len1 = x[pre[k].r+1] - x[pre[k].l];
else if (pre[k].l == pre[k].r) pre[k].len1 = 0;
else pre[k].len1 = pre[k<<1].len1 + pre[k<<1|1].len1;
// 区别于矩形面积并得地方,多有一个检测是否有被覆盖两次的边
// 要注意这几个 if else 的顺序 ,顺序不一样就会错哦 , 可以想想为什么
if (pre[k].sum >= 2) pre[k].len2 = pre[k].len1;
else if (pre[k].l == pre[k].r) pre[k].len2 = 0;
else if (pre[k].sum == 1) pre[k].len2 = pre[k<<1].len1 + pre[k<<1|1].len1;
else pre[k].len2 = pre[k<<1].len2 + pre[k<<1|1].len2;
}
void update(int l, int r, int k, int pt){
if (l <= pre[k].l && pre[k].r <= r){
pre[k].sum += pt;
down(k);
return;
}
int m = (pre[k].l + pre[k].r) >> 1;
// 这个地方当时写完有一个BUG ,一顿找啊 我是,就是自己写线段树,习惯了 l , m , k<<1 这样的参数传递,实则不然
if (l <= m) update(l, r, k<<1, pt);
if (r > m) update(l, r, k<<1|1, pt);
down(k);
}
int main() {
int t, n;
double a, b, c, d;
cin >>t;
while (t--){
cin >> n;
int k = 1;
for(int i = 0; i < n; i++){
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
po[k].l = po[k+1].l = a;
po[k].r = po[k+1].r = c;
po[k].h = b, po[k+1].h = d;
po[k].f = 1, po[k+1].f = -1;
x[k] = a, x[k+1] = c;
k += 2;
}
sort(x+1, x+k);
sort(po+1, po+k, cmp);
int t = 2;
for(int i = 2; i < k; i++){
if (x[i] != x[i-1]) x[t++] = x[i];
}
build(1, t-1, 1);
double ans = 0;
for(int i = 1; i < k; i++){
int l = lower_bound(x+1, x+t, po[i].l) - x;
int r = lower_bound(x+1, x+t, po[i].r) - x - 1;
update(l, r, 1, po[i].f);
ans += pre[1].len2*(po[i+1].h - po[i].h);
}
printf("%.2f\n", ans);
}
return 0;
}