题意
给定多个矩形,会出现重叠的情况,问总面积是多少?
解法
采用了线段树+扫描线的做法,
一些小技巧
- 离散化: 先用sort进行需要离散的数据排须,然后用unique进行去重复。
unique()函数的参数和sort函数一致,将重复的元素放到数组的最后面,返回值是最后一个unique的数地址+1。 - 这里面有个很莫名其妙的部分就是update的时候r要先减1,之后在进行区间长度计算的时候r再加回来,如果不进行这样的处理,会出现没法计算区间长度的情况。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100 + 10;
struct segment{
double l, r, h;
int f;
}segments[2 * maxn];
int n, sn, pos_num, coverv[2 * 4 * maxn];
double pos[2 * maxn],lenv[2 * 4 * maxn];
int cmp(segment a, segment b){
if(a.h < b.h) return 1;
else return 0;
}
void maintain(int o, int L, int R){
if(coverv[o]) lenv[o] = pos[R + 1] - pos[L];
else if(L == R){
lenv[o] = 0;
}
else lenv[o] = lenv[o << 1] + lenv[o << 1 | 1];
}
void update(int o, int l, int r, int L, int R, int v){
if(l <= L && r >= R){
coverv[o] += v;
}
else{
int M = L + (R - L) / 2;
if(l <= M) update(o << 1, l, r, L, M, v);
if(r > M) update(o << 1 | 1, l, r, M + 1, R, v);
}
maintain(o, L, R);
}
int main(){
//freopen("input.txt", "r", stdin);
int t = 0;
while(scanf("%d", &n) != EOF){
if(n == 0) break;
t ++;
printf("Test case #%d\n", t);
printf("Total explored area: ");
memset(pos, 0, sizeof(pos));
memset(coverv, 0, sizeof(coverv));
memset(lenv, 0, sizeof(lenv));
sn = 0;
pos_num = 0;
for(int i = 1; i <= n; i++){
double x1, y1, x2, y2;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
segments[sn].l = x1;
segments[sn].r = x2;
segments[sn].h = y1;
segments[sn].f = 1;
sn ++;
segments[sn].l = x1;
segments[sn].r = x2;
segments[sn].h = y2;
segments[sn].f = -1;
sn ++;
pos[pos_num++] = x1;
pos[pos_num++] = x2;
}
sort(pos, pos + pos_num);
sort(segments, segments + sn, cmp);
pos_num = unique(pos, pos + pos_num) - pos;
//cout << pos_num <<endl;
double ans = 0;
for(int i = 0; i < sn; i++){
int l = lower_bound(pos, pos + pos_num, segments[i].l) - pos;
int r = lower_bound(pos, pos + pos_num, segments[i].r) - pos -1;
//cout << l << r << endl;
update(1, l, r, 0, pos_num - 1, segments[i].f);
//cout << lenv[1] <<"("<< lenv[2] <<","<<lenv[3]<<")" << " " << (segments[i+1].h - segments[i].h) << endl;
ans += lenv[1] * (segments[i+1].h - segments[i].h);
}
printf("%.2lf\n\n", ans);
}
return 0;
}