求解矩形覆盖面积 (线段树 + 扫描线)
扫描线算法流程:
1、想象一下有一条平行于y轴的直线,正在从左边缓缓向右平移……
2、再想像一下y轴上有一棵线段树,它记录的是y轴上每个点的覆盖次数
3、每当遇到某个矩形的某一条边时,就计算面积——用这次碰边的x坐标减去上一次碰边时的x坐标,再用这个差值乘以当前y轴上有多少个点被覆盖
4、当这条直线遇到某个矩形的左边时,将这个矩形的左边所对应的y轴区间的覆盖次数+1,当遇到某个矩形的右边时,就相应的-1
5、让这条线继续向右移动……
然后我的这个板子不采取离散化的原因是因为我魔改了线段树,普通的线段树是维护的连续的点,而我的这个线段树维护的是真正的“线段”
板子题:https://www.luogu.org/problem/P5490
1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <iostream> 5 #include <algorithm> 6 #include <string> 7 #include <string.h> 8 #include <vector> 9 #include <map> 10 #include <stack> 11 #include <set> 12 #include <random> 13 14 #define LL long long 15 #define ls nod<<1 16 #define rs (nod<<1)+1 17 const int maxn = 2e5 + 10; 18 19 int v[maxn]; 20 21 struct L { 22 int x; 23 int y1,y2; 24 int state; 25 bool operator <(const L &ith) const{ 26 return x<ith.x; 27 } 28 }line[maxn]; 29 30 struct segment_tree { 31 int l,r; 32 int cover; 33 LL len; 34 }tree[maxn<<3]; 35 36 void pushup(int nod) { 37 if (tree[nod].cover) { 38 tree[nod].len = (tree[nod].r - tree[nod].l); 39 } 40 else { 41 tree[nod].len = (tree[ls].len + tree[rs].len); 42 } 43 } 44 45 void build(int l,int r,int nod=1) { 46 tree[nod].l = v[l]; 47 tree[nod].r = v[r]; 48 if (r-l <= 1) 49 return ; 50 int mid = (l + r) >> 1; 51 build(l,mid,ls); 52 build(mid,r,rs); 53 } 54 55 void modify(int x,int y,int z,int nod=1) { 56 int l = tree[nod].l,r = tree[nod].r; 57 if (x <= l && y >= r){ 58 tree[nod].cover += z; 59 pushup(nod); 60 return ; 61 } 62 if (x < tree[ls].r) 63 modify(x,y,z,ls); 64 if (y > tree[rs].l) 65 modify(x,y,z,rs); 66 pushup(nod); 67 } 68 69 int main() { 70 int n; 71 int a,b,c,d; 72 scanf("%d",&n); 73 for (int i=1;i<=n;i++) { 74 scanf("%d%d%d%d",&a,&b,&c,&d); 75 v[i] = b; 76 v[n+i] = d; 77 line[i] = (L){a,b,d,1}; 78 line[i+n] = (L){c,b,d,-1}; 79 } 80 std::sort(v+1,v+1+(n<<1)); 81 std::sort(line+1,line+1+(n<<1)); 82 build(1,n<<1); 83 unsigned long long ans = 0; 84 for (int i=1;i<=2*n;i++) { 85 ans += tree[1].len*(line[i].x-line[i-1].x); 86 modify(line[i].y1,line[i].y2,line[i].state); 87 } 88 std::cout << ans << std::endl; 89 return 0; 90 }
板子题:
https://vjudge.net/contest/332656#problem/K
题意:
二维平面有n个平行于坐标轴的矩形,现在要求出这些矩形的总面积. 重叠部分只能算一次.
1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <iostream> 5 #include <algorithm> 6 #include <string> 7 #include <string.h> 8 #include <vector> 9 #include <map> 10 #include <stack> 11 #include <set> 12 #include <random> 13 14 #define LL long long 15 #define ls nod<<1 16 #define rs (nod<<1)+1 17 const int maxn = 2e5 + 10; 18 19 double v[maxn]; 20 21 struct L { 22 double x; 23 double y1,y2; 24 int state; 25 bool operator <(const L &ith) const{ 26 return x<ith.x; 27 } 28 }line[maxn]; 29 30 struct segment_tree { 31 double l,r; 32 int cover; 33 double len; 34 }tree[maxn<<3]; 35 36 void pushup(int nod) { 37 if (tree[nod].cover) { 38 tree[nod].len = (tree[nod].r - tree[nod].l); 39 } 40 else { 41 tree[nod].len = (tree[ls].len + tree[rs].len); 42 } 43 } 44 45 void build(int l,int r,int nod=1) { 46 tree[nod].l = v[l]; 47 tree[nod].r = v[r]; 48 if (r-l <= 1) 49 return ; 50 int mid = (l + r) >> 1; 51 build(l,mid,ls); 52 build(mid,r,rs); 53 } 54 55 void modify(double x,double y,int z,int nod=1) { 56 double l = tree[nod].l,r = tree[nod].r; 57 if (x <= l && y >= r){ 58 tree[nod].cover += z; 59 pushup(nod); 60 return ; 61 } 62 if (x < tree[ls].r) 63 modify(x,y,z,ls); 64 if (y > tree[rs].l) 65 modify(x,y,z,rs); 66 pushup(nod); 67 } 68 69 int main() { 70 int n; 71 double a,b,c,d; 72 int t = 1; 73 while(~scanf("%d",&n)) { 74 if (n == 0) 75 break; 76 printf("Test case #%d\n",t++); 77 for (int i = 1; i <= n; i++) { 78 scanf("%lf%lf%lf%lf", &a, &b, &c, &d); 79 v[i] = b; 80 v[n + i] = d; 81 line[i].x = a; 82 line[i].y1 = b; 83 line[i].y2 = d; 84 line[i].state = 1; 85 line[i+n].x = c; 86 line[i+n].y1 = b; 87 line[i+n].y2 = d; 88 line[i+n].state = -1; 89 } 90 std::sort(v + 1, v + 1 + (n << 1)); 91 std::sort(line + 1, line + 1 + (n << 1)); 92 build(1, n << 1); 93 double ans = 0; 94 for (int i = 1; i <= 2 * n; i++) { 95 ans += tree[1].len * (line[i].x - line[i - 1].x); 96 modify(line[i].y1, line[i].y2, line[i].state); 97 } 98 printf("Total explored area: %.2lf\n\n",ans); 99 } 100 return 0; 101 }