题目链接:点击打开链接
题意:给你n个矩形, 求这n个矩形所覆盖的面积(重复覆盖算一次)
思路:我们可以考虑, 将y坐标保存并排序。 按x坐标离散化后建立线段树。 每次遇到一个矩形的下底边就将这个区间+1,表示这个区间已经被几条线段覆盖了。 遇到上边就-1, 每次更新后累加当前x坐标总区间被覆盖的长度乘以相邻两边的高度。 具体原因可以画图看看就明白了。 另外很重要的一点就是, 线段树都是维护一个点集, 但是对于边的问题就会变得很麻烦, 我们可以按照区间左端点建立线段树, 那么一个点表示的就不是点了, 而是起点在这个点的一个线段。 这样的话, 右区间就要相应的-1, 例如更新区间[1, 4], 就相当于更新标号为[1, 3]的线段。
这也是处理线段覆盖问题的通用方法。
细节参见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 100000 + 10;
int T,n,m,kase=0,addv[maxn<<2];
double sum[maxn<<2],c[maxn];
struct node {
double xl, xr, h;
int id;
node(double xl=0, double xr=0, double h=0, int id=0):xl(xl),xr(xr),h(h),id(id) {}
bool operator < (const node& rhs) const {
return h < rhs.h;
}
}b[maxn];
void PushUp(int l, int r, int o) {
if(addv[o]) sum[o] = c[r+1] - c[l]; //当前区间被线段覆盖
else if(l == r) sum[o] = 0; // 已经到了叶子结点且没有被覆盖
else sum[o] = sum[o<<1] + sum[o<<1|1]; // 没有完全被覆盖, 但是还没到叶子结点, 从其子区间中获得信息
}
void build(int l, int r, int o) {
int m = (l + r) >> 1;
addv[o] = 0;
sum[o] = 0;
if(l == r) return ;
build(l, m, o<<1);
build(m+1, r, o<<1|1);
}
void update(int L, int R, int x, int l, int r, int o) {
int m = (l + r) >> 1;
if(L <= l && r <= R) {
addv[o] += x;
PushUp(l, r, o);
return ;
}
if(L <= m) update(L, R, x, l, m, o<<1);
if(m < R) update(L, R, x, m+1, r, o<<1|1);
PushUp(l, r, o);
}
double xl, xr, yl, yr;
int main() {
while(~scanf("%d",&n) && n) {
int cnt = 0, res = 0;
for(int i=0;i<n;i++) {
scanf("%lf%lf%lf%lf",&xl,&yl,&xr,&yr);
b[++cnt] = node(xl, xr, yl, 1); c[++res] = xl;
b[++cnt] = node(xl, xr, yr, -1); c[++res] = xr;
}
sort(b+1, b+cnt+1);
sort(c+1, c+res+1);
int m = unique(c+1, c+res+1) - c - 1;
build(1, m, 1);
double ans = 0;
for(int i=1;i<cnt;i++) {
xl = lower_bound(c+1, c+1+m, b[i].xl) - c;
xr = lower_bound(c+1, c+m+1, b[i].xr) - c - 1;
update(xl, xr, b[i].id, 1, m, 1);
ans += (b[i+1].h - b[i].h) * sum[1];
}
printf("Test case #%d\n",++kase);
printf("Total explored area: %.2f\n\n",ans);
}
return 0;
}