覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3353 Accepted Submission(s): 1638
Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
注意:本题的输入数据较多,推荐使用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
Author
Ignatius.L & weigang Lee
传送门:【HDU】1255 覆盖的面积
题目分析:
求矩阵面积交。
once[]表示区间覆盖一次或以上的长度。
more[]表示区间覆盖两次或以上的长度。
如果当前区间被覆盖两次或以上,则once[]和more[]等同,可以直接用自己的信息更新自己。
如果当前区间被覆盖一次或以上,则once[]可以用自己的信息更新自己,more用子节点的once[]更新自己。
如果当前区间没有覆盖标记,则once[]用子节点的once[]更新自己,more[]用子节点的more[]更新自己。
传递思想与求矩阵面积并类似,而且最后本题的once[]就是矩阵面积并。
PS:写完后,答案和样例一直对不上,查了很久的错,很多地方输出了中间结果,发现就more[]得到的值特别奇怪,然后顺着这里找啊找,找到了二分查找里面,看着看着很正常啊没什么不对的。。。。。后来再次查到二分的时候突然发现。。。。没有加else导致l一直增大。。。改了以后,样例对上了,也直接AC了T T。真是苦
代码如下:
传送门:【HDU】1255 覆盖的面积
题目分析:
求矩阵面积交。
once[]表示区间覆盖一次或以上的长度。
more[]表示区间覆盖两次或以上的长度。
如果当前区间被覆盖两次或以上,则once[]和more[]等同,可以直接用自己的信息更新自己。
如果当前区间被覆盖一次或以上,则once[]可以用自己的信息更新自己,more用子节点的once[]更新自己。
如果当前区间没有覆盖标记,则once[]用子节点的once[]更新自己,more[]用子节点的more[]更新自己。
传递思想与求矩阵面积并类似,而且最后本题的once[]就是矩阵面积并。
PS:写完后,答案和样例一直对不上,查了很久的错,很多地方输出了中间结果,发现就more[]得到的值特别奇怪,然后顺着这里找啊找,找到了二分查找里面,看着看着很正常啊没什么不对的。。。。。后来再次查到二分的时候突然发现。。。。没有加else导致l一直增大。。。改了以后,样例对上了,也直接AC了T T。真是苦

代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define rt o , l , r
#define root 1 , 1 , n
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define clear( A , X ) memset ( A , X , sizeof A )
const int maxN = 2048 ;
const double eps = 1e-6 ;
struct Line {
double l , r , h ;
int f ;
Line () {}
Line ( double L , double R , double H , int F ) : l(L) , r(R) , h(H) , f(F) {}
bool operator < ( const Line &L ) const {
return h < L.h ;
}
} ;
Line line[maxN] ;
int cover[maxN << 2] ;
double a[maxN] ;
double once[maxN << 2] , more[maxN << 2] ;
int sgn ( double x ) {
return ( x > eps ) - ( x < -eps ) ;
}
int Search ( double x , int l , int r ) {
while ( l < r ) {
int m = mid ;
if ( sgn ( a[m] - x ) >= 0 ) r = m ;
else l = m + 1 ;
}
return l ;
}
int Unique ( double *a , int n ) {
int cnt = 1 ;
sort ( a + 1 , a + n + 1 ) ;
for ( int i = 2 ; i <= n ; ++ i ) {
if ( sgn ( a[i] - a[cnt] ) ) a[++ cnt] = a[i] ;
}
return cnt ;
}
void PushUp ( int o , int l , int r ) {
if ( cover[o] >= 2 ) {
more[o] = once[o] = a[r + 1] - a[l] ;
}
else if ( cover[o] == 1 ) {
once[o] = a[r + 1] - a[l] ;
if ( l == r ) more[o] = 0 ;
else more[o] = once[ls] + once[rs] ;
}
else {
if ( l == r ) more[o] = once[o] = 0 ;
else{
once[o] = once[ls] + once[rs] ;
more[o] = more[ls] + more[rs] ;
}
}
}
void Update ( int L , int R , int v , int o , int l , int r ) {
if ( L <= l && r <= R ) {
cover[o] += v ;
PushUp ( rt ) ;
return ;
}
int m = mid ;
if ( L <= m ) Update ( L , R , v , lson ) ;
if ( m < R ) Update ( L , R , v , rson ) ;
PushUp ( rt ) ;
}
void work () {
int n , cnt = 0 , __cnt = 0 ;
double x1 , x2 , y1 , y2 ;
clear ( once , 0 ) ;
clear ( more , 0 ) ;
clear ( cover , 0 ) ;
scanf ( "%d" , &n ) ;
for ( int i = 0 ; i < n ; ++ i ) {
scanf ( "%lf%lf%lf%lf" , &x1 , &y1 , &x2 , &y2 ) ;
line[++ __cnt] = Line ( x1 , x2 , y1 , 1 ) ;
line[++ __cnt] = Line ( x1 , x2 , y2 , -1 ) ;
a[++ cnt] = x1 ;
a[++ cnt] = x2 ;
}
cnt = Unique ( a , cnt ) ;
/*
printf ( "cnt = %d\n" , cnt ) ;
for ( int i = 1 ; i <= cnt ; ++ i ) printf ( "a[%d] = %.2f\n" , i , a[i] ) ;
*/
n = __cnt ;
sort ( line + 1 , line + n + 1 ) ;
double area = 0 ;
for ( int i = 1 ; i < n ; ++ i ) {
int L = Search ( line[i].l , 1 , cnt + 1 ) ;
int R = Search ( line[i].r , 1 , cnt + 1 ) ;
Update ( L , R - 1 , line[i].f , 1 , 1 , cnt - 1 ) ;
area += ( line[i + 1].h - line[i].h ) * more[1] ;
}
printf ( "%.2f\n" , area ) ;
}
int main () {
int T ;
scanf ( "%d" , &T ) ;
while ( T -- ) work () ;
return 0 ;
}