给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
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 = 1010;
struct f
{
double l, r, h;
int flag;
}line[MAXN * 2];
struct node
{
int l, r;
double one_len, more_len;
bool ye;
int lazy;
}tree[MAXN * 8];
double temp[MAXN * 2];
bool com(f u, f v)
{
return u.h < v.h;
}
void build( int l, int r, int rt )
{
tree[rt].l = l; tree[rt].r = r;
tree[rt].one_len = tree[rt].more_len = 0;
tree[rt].lazy = 0;
tree[rt].ye = 0;
if( l + 1 == r )
{
tree[rt].ye = 1;
return;
}
int mid = ( l + r ) >> 1;
build( l, mid, rt << 1 );
build( mid, r, rt << 1 | 1 );
}
void push(int rt)
{
if(tree[rt].lazy > 1)
tree[rt].one_len = tree[rt].more_len = temp[tree[rt].r] - temp[tree[rt].l];
else if(tree[rt].lazy == 1)
{
tree[rt].one_len = tree[rt].more_len = temp[tree[rt].r] - temp[tree[rt].l];;
if(tree[rt].l + 1 == tree[rt].r)
tree[rt].more_len = 0;
else
tree[rt].more_len = tree[rt << 1].one_len + tree[rt << 1 | 1].one_len;
}
else
{
if(tree[rt].l + 1 == tree[rt].r)
tree[rt].one_len = tree[rt].more_len = 0;
else
{
tree[rt].one_len = tree[rt << 1].one_len + tree[rt << 1 | 1].one_len;
tree[rt].more_len = tree[rt << 1].more_len + tree[rt << 1 | 1].more_len;
}
}
}
void update(int x, int y, int l, int r, int rt, int q)
{
if(l >= x && r <= y)
{
tree[rt].lazy += q;
push(rt);
return;
}
int mid = (l + r) >> 1;
if(mid > x)
update(x, y, l, mid, rt << 1, q);
if(mid < y)
update(x, y, mid, r, rt << 1 | 1, q);
push(rt);
}
int main()
{
int T, n;
int cas = 0;
double x1, y1, x2, y2;
scanf("%d", &T);
while( T -- )
{
scanf("%d", &n);
cas ++;
int tot = 0;
for( int i = 1; i <= n; i ++ )
{
scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
tot ++;
line[tot].l = x1; line[tot].r = x2;
line[tot].h = y1; line[tot].flag = 1;
temp[tot] = x1;
tot ++;
line[tot].l = x1; line[tot].r = x2;
line[tot].h = y2; line[tot].flag = -1;
temp[tot] = x2;
}
sort( temp + 1, temp + tot + 1 );
sort( line + 1, line + tot + 1, com );
int k = 1;
for( int i = 2; i <= tot; i ++ )
{
if( temp[i] != temp[i - 1] )
{
k ++ ;
temp[k] = temp[i];
}
}
//cout << k << endl;
build( 1, k , 1 );
double ans = 0;
//for(int i = 1; i <= k ; i ++)
// cout << temp[i] << " " ;
//cout << endl;
for( int i = 1; i < tot; i ++ )
{
int L = lower_bound( temp + 1, temp + k + 1, line[i].l ) - temp;
int R = lower_bound( temp + 1, temp + k + 1, line[i].r ) - temp;
//cout << L << " " << R << endl;
update( L, R, 1, k, 1, line[i].flag );
//cout << "!" << tree[1].more_len << endl;
//for(int j = 1; j <= 15 ; j ++)
// cout << tree[j].lazy << " " << tree[j].one_len << " " << tree[j].more_len << endl;
ans += 1.00 * tree[1].more_len * ( line[i + 1].h - line[i].h);
//cout << "!!" << ans << endl;
}
printf("%.2lf\n",ans);
}
return 0;
}