用len1[]表示相应区间覆盖了一次的长度,用len2[]表示相应区间覆盖了2次或2次以上的长度.cnt[]表示响应区间覆盖的次数.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 1005
using namespace std;
struct Node{
Node(){
}
Node(double a, double b, double c, int d){
x1 = a;
x2 = b;
y = c;
flag = d;
}
double x1, x2, y, flag;
friend bool operator < (const Node &a, const Node&b){
return a.y < b.y;
}
}node[maxn<<1];
double len1[maxn<<3], len2[maxn<<3], p[maxn<<1];
int cnt[maxn<<3];
void Pushup(int n, int l, int r){
if(cnt[n] >= 2){
len2[n] = p[r+1] - p[l];
len1[n] = 0;
}
else if(cnt[n] == 1){
len1[n] = p[r+1] - p[l];
if(l != r)
len2[n] = len1[n<<1] + len1[n<<1|1] + len2[n<<1] + len2[n<<1|1];
else
len2[n] = 0;
len1[n] -= len2[n];
}
else {
if(l == r){
len1[n] = len2[n] = 0;
}
else {
len1[n] = len1[n<<1] + len1[n<<1|1];
len2[n] = len2[n<<1] + len2[n<<1|1];
}
}
}
void Update(int n, int l, int r, int L, int R, int s){
if(l == L && R == r){
cnt[n] += s;
Pushup(n, l, r);
return ;
}
int mid = (l + r) >> 1;
if(R <= mid)
Update(n<<1, l, mid, L, R, s);
else if(L > mid)
Update(n<<1|1, mid+1, r, L, R, s);
else{
Update(n<<1, l, mid, L, mid, s);
Update(n<<1|1, mid+1, r, mid+1, R, s);
}
Pushup(n, l, r);
}
int main(){
//freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while(t--){
memset(cnt, 0, sizeof(cnt));
memset(len1, 0, sizeof(len1));
memset(len2, 0, sizeof(len2));
double a, b, c, d;
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
node[2*i-1] = Node(a, c, b, 1);
node[2*i] = Node(a, c, d, -1);
p[2*i-1] = a;
p[2*i] = c;
}
sort(node+1, node+1+2*n);
sort(p+1, p+1+2*n);
int dd = unique(p+1, p+1+2*n) - p - 1;
double sum = 0;
for(int i = 1; i < 2*n; i++){
int l = lower_bound(p+1, p+1+dd, node[i].x1) - p;
int r = lower_bound(p+1, p+1+dd, node[i].x2) - p;
if(l == r)
continue;
Update(1, 1, dd, l, r-1, node[i].flag);
sum += len2[1] * (node[i+1].y - node[i].y);
}
printf("%.2f\n", sum);
}
return 0;
}