zoukankan      html  css  js  c++  java
  • 求解矩形覆盖面积 (线段树 + 扫描线)

    扫描线算法流程:

    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
    ",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
    
    ",ans);
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    关于书签(BookMark)操作;
    清理内存
    string系列操作1
    SQL临时表
    线程,临界区的研究
    Unix 纪元时间
    shell 模仿验证登陆密码
    delphi字符串中取数字
    delphi MD5加密,BASE64加解密
    delphi sendGetIntmessage、sendStructMessage、sendGetStructMessage和sendTextMessage函数的用法
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11734604.html
Copyright © 2011-2022 走看看