HDU1255 - 覆盖的面积 (扫描线求面积)
Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
思路
和单纯的求面积非常相似,用len来储存被覆盖到两次以上的区间长度。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N = 3000;
struct snode {
double x, y1, y2;
int flag;
};
bool cmp(const snode &a, const snode &b) {
return a.x < b.x;
}
struct tnode {
double sum, l, r, len;
};
tnode st[N << 2];
snode seg[N];
double num[N];
int lazy[N << 2];
void pushup(int rt) {
if(lazy[rt] > 0) {
st[rt].sum = st[rt].r - st[rt].l;
if(lazy[rt] > 1) st[rt].len = st[rt].sum;
else st[rt].len = st[rt << 1].sum + st[rt << 1 | 1].sum;
} else {
st[rt].sum = st[rt << 1].sum + st[rt << 1 | 1].sum;
st[rt].len = st[rt << 1].len + st[rt << 1 | 1].len;
}
}
void update(double L, double R, int rt, int flag) {
if(L == st[rt].l && R == st[rt].r) {
lazy[rt] += flag;
pushup(rt);
return ;
}
if(st[rt << 1].r > L) //>而不是>=?不能等于,否则长度为0,会进入死循环。
update(L, min(R, st[rt << 1].r), rt << 1, flag);
if(st[rt << 1 | 1].l < R)
update(max(L, st[rt << 1 | 1].l), R, rt << 1 | 1, flag);
pushup(rt);
}
void build(int lef, int rig, int rt) {
if(rig - lef > 1) { //由于mid公用,所以>1就可以
int mid = (lef + rig) / 2;
st[rt].l = num[lef];
st[rt].r = num[rig];
build(lef, mid, rt << 1);
build(mid, rig, rt << 1 | 1); //mid而不是mid+1?因为是线段,头尾需要相连,否则会少值
pushup(rt);
} else {
st[rt].l = num[lef];
st[rt].r = num[rig];
st[rt].sum = 0;
st[rt].len = 0;
}
}
int main() {
//ios::sync_with_stdio(false);
int n;
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
if(!n) break;
for(int i = 0; i < n; i++) {
double x1, x2, y1, y2;
scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
seg[i].x = x1; seg[i].y1 = y1; seg[i].y2 = y2;
seg[i].flag = 1;
seg[i + n].x = x2; seg[i + n].y1 = y1; seg[i + n].y2 = y2;
seg[i + n].flag = -1;
num[i + 1] = y1;
num[i + 1 + n] = y2;
}
sort(num + 1, num + 1 + (2 * n));
sort(seg, seg + 2 * n, cmp);
memset(lazy, 0, sizeof lazy);
build(1, 2 * n, 1);
double ans = 0;
update(seg[0].y1, seg[0].y2, 1, seg[0].flag);
for(int i = 1; i < 2 * n; i++) {
ans += (seg[i].x - seg[i - 1].x) * st[1].len;
//cout << st[1].len << endl;
update(seg[i].y1, seg[i].y2, 1, seg[i].flag);
//cout << seg[i].x << " " << seg[i].y1 << " " << seg[i].y2 << endl;
}
printf("%.2lf\n", ans);
//printf("Total explored area: %.2lf\n\n", ans);
}
}