HDU-1255 覆盖的面积 (线段树 求矩形覆盖面积)

来源:互联网 发布:超牛手机数据恢复软件 编辑:程序博客网 时间:2024/06/06 09:55

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6458    Accepted Submission(s): 3286


Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.


 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.
 

Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
 

Sample Input
251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 0 2 12 0 3 1
 

Sample Output
7.630.00


#include <bits/stdc++.h>using namespace std;const int maxn = 1001;struct Xpoint{double x, l, r;int v;bool operator < (const Xpoint& e){return x < e.x;}}line[maxn << 1];struct tree{int cover;double len1, len2;}c[maxn << 4];double y[maxn << 2];void build(int o, int l, int r){c[o].cover = c[o].len1 = c[o].len2 = 0;if(l == r - 1) return;int mid = l + r >> 1;build(o << 1, l, mid);build(o << 1 | 1, mid, r);}void pushup(int o, int l, int r){if(c[o].cover > 0){c[o].len1 = y[r] - y[l];}else if(l == r - 1){c[o].len1 = 0;}else{c[o].len1 = c[o << 1].len1 + c[o << 1 | 1].len1;}if(c[o].cover > 1){c[o].len2 = y[r] - y[l];}else if(l == r - 1){c[o].len2 = 0;}else if(c[o].cover == 1){c[o].len2 = c[o << 1].len1 + c[o << 1 | 1].len1;   //如果当前被完全覆盖了一层,那么不连续的子区间就是第二层覆盖}else c[o].len2 = c[o << 1].len2 + c[o << 1 | 1].len2;}void add(int o, int l, int r, int L, int R, int v){if(l >= R || r <= L) return;if(l >= L && r <= R){c[o].cover += v;pushup(o, l, r);return;}int mid = l + r >> 1;add(o << 1, l, mid, L, R, v);add(o << 1 | 1, mid, r, L, R, v);pushup(o, l, r);}int main(){int n, T;scanf("%d", &T);double x1, x2, y1, y2;while(T--){scanf("%d", &n);int tot = 0;for(int i = 1; i <= n; ++i){scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);line[++tot].x = x1;line[tot].l = y1;line[tot].r = y2;line[tot].v = 1;y[tot] = y1;line[++tot].x = x2;line[tot].l = y1;line[tot].r = y2;line[tot].v = -1;y[tot] = y2;}build(1, 1, tot);sort(y + 1, y + 1 + tot);sort(line + 1, line + 1 + tot);double ans = 0;for(int i = 1; i < tot; ++i){y1 = lower_bound(y + 1, y + 1 + tot, line[i].l) - y;y2 = lower_bound(y + 1, y + 1 + tot, line[i].r) - y;add(1, 1, tot, y1, y2, line[i].v);ans += c[1].len2 * (line[i + 1].x - line[i].x);}printf("%.2lf\n", ans);}}/*题意:1000个矩形,坐标范围1e5,求所有矩形的总覆盖面积。思路:我们把y轴映射到线段树上,离散化一下,按照x的坐标从小到大依次处理所有矩形的平行于y轴的边。每一个矩形x坐标小的边表示后面这个区域是被覆盖的,直到遇到x大的边结束。那么我们对于所有矩形左边的边,我们讲其加到线段树的区间上,这样每处理一条边,区间上被覆盖的区间长度可以计算出来,即这一段y轴的区域是被覆盖的,再利用x算一下这一段的面积。一直处理完所有面积即可。这一题需要主要的是需要维护两次覆盖,计算覆盖区间时需要分类讨论一下。*/


阅读全文
0 0