Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Solution
这道题也是类似的,只要在统计的时候看看是否被覆盖两次就可以了。n很大所以艹到底的线段树有点吃力
1A
Code
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define db double
#define N 4001
using namespace std;
struct treeNode{int l, r, c;}t[N * 5];
struct segement{db x; int l, r, c;}s[N];
struct data{db x; int index;}p[N];
int hy[N];
db lx[N], len;
inline void modify(int now, int l, int r, int v){
if (t[now].l + 1 == t[now].r){
t[now].c += v;
if (t[now].c == 1 && v == -1){
len -= (lx[r] - lx[l]);
}else if (t[now].c == 2 && v == 1){
len += (lx[r] - lx[l]);
}
return;
}else{
int mid = (t[now].l + t[now].r) >> 1;
if (r <= mid){
modify(now * 2, l, r, v);
}else if (l >= mid){
modify(now * 2 + 1, l, r, v);
}else{
modify(now * 2, l, mid, v);
modify(now * 2 + 1, mid, r, v);
}
}
}
inline void build(int now, int l, int r){
t[now] = (treeNode){l, r, 0};
if (l + 1 == r){
return;
}
int mid = (l + r) >> 1;
build(now * 2, l, mid);
build(now * 2 + 1, mid, r);
}
inline int cmp1(data a, data b){
return a.x < b.x;
}
inline int cmp2(segement a, segement b){
return a.x < b.x;
}
int main(void){
int T = 0;
scanf("%d", &T);
while (T --){
vector<data> v;
vector<segement> e;
int n;
scanf("%d", &n);
rep(i, 1, n){
db u, l, d, r;
scanf("%lf%lf%lf%lf", &u, &l, &d, &r);
v.push_back((data){l, i * 2 - 1});
v.push_back((data){r, i * 2});
e.push_back((segement){u, i * 2 - 1, i * 2, 1});
e.push_back((segement){d, i * 2 - 1, i * 2, -1});
}
sort(v.begin(), v.end(), cmp1);
int cnt = 1;
hy[v[0].index] = cnt;
lx[1] = v[0].x;
rep(i, 1, v.size() - 1){
if (v[i].x != v[i - 1].x){
cnt += 1;
}
hy[v[i].index] = cnt;
lx[cnt] = v[i].x;
}
build(1, 1, cnt);
rep(i, 0, e.size() - 1){
e[i].l = hy[e[i].l];
e[i].r = hy[e[i].r];
}
sort(e.begin(), e.end(), cmp2);
len = 0;
db tot = 0;
rep(i, 0, e.size() - 2){
modify(1, e[i].l, e[i].r, e[i].c);
tot += (e[i + 1].x - e[i].x) * len;
}
printf("%.2f\n", tot);
}
return 0;
}