• poj1151 扫描线~


    555搞了这么久算法居然才学扫描线......

    愧疚愧疚

    扫描线也不算是一种算法,实际上是一种技♂巧

    在处理矩形覆盖类的问题(目前只做了矩形覆盖hhh)时,我们将每个矩形的上下两条底边存储,记录左、右的坐标以及它距离x轴的高度h,同时定义一个标记tag为1/-1来表明它是上底边还是下底边。

    与此同时也要存储线段的两个端点的横坐标于一个数组内,用于离散化。

    随后我们去枚举每一条线段,采用离散化获得的下标进行线段树上的处理。

    线段树中的节点存储一个cnt,用来判断求出当前节点的有效长度len。

    1.如果cnt不为0,则len为当前区间的总长。

    2.如果当前节点的l,r相等,则区间长度为0,毕竟是同一个点嘛。

    3.不属于1/2的情况,则len取子节点len之和

    然后我们发现,当合并区间[a, b]与[b + 1, c]时,我们少计算了[b, b + 1]这一小段间距。

    所以在1中,我们求长度必须取X[r + 1] - X[l]才可以。

    相对应的,在离散化取总的l与r时,r取r - 1,就恰好抵消啦!超棒哒!

    当我们获得了这个len,只需要取得下一条线段与当前线段的高度h之差,二者的乘积就形成了一小块有效面积。

    芜湖

    如果题目给定的点是左上&右下,记得转化一下,两个swap即可。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #define rg register
     7 using namespace std;
     8 
     9 const int N = 110;
    10 
    11 struct seg
    12 {
    13     double l, r, h;
    14     int tag;//1-下底边 0-上底边
    15     seg(){}
    16     seg(double ll, double rr, double hh, int tagg){
    17         l = ll, r = rr, h = hh, tag = tagg;
    18     }
    19     bool operator < (const seg &i)const{
    20         return h < i.h;
    21     }
    22 }e[N << 1];
    23 
    24 struct node
    25 {
    26     int cnt;
    27     double len;
    28     node(){}
    29     node(int cntt, int lenn){
    30         cnt = cntt, len = lenn;
    31     }
    32 }t[N << 3];
    33 
    34 double X[N << 1];
    35 
    36 inline void push_up(int root, int l, int r)
    37 {
    38     if(t[root].cnt){
    39         t[root].len = X[r + 1] - X[l];//合并时必须保证连续,r取多1 
    40     }else if(l == r){
    41         t[root].len = 0;
    42     }else{
    43         t[root].len = t[root << 1].len + t[root << 1 | 1].len;
    44     }
    45 }
    46 
    47 inline void upd(int L, int R, int l, int r, int root, int tag)
    48 {
    49     if(r < L || l > R)    return ;
    50     if(l >= L && r <= R){
    51         t[root].cnt += tag;
    52         push_up(root, l, r);
    53         return ;
    54     }
    55     int mid = (l + r) >> 1;
    56     upd(L, R, l, mid, root << 1, tag);
    57     upd(L, R, mid + 1, r, root << 1 | 1, tag);
    58     push_up(root, l, r);
    59 }
    60 
    61 int main(){
    62     int n, cas = 1;
    63     while(~scanf("%d",&n)){
    64         if(n == 0)    break;
    65         for(rg int i = 0 ; i <= n ; i++){
    66             t[i].cnt = t[i].len = 0;
    67         }
    68         int tot = 0;
    69         double a, b, c, d;
    70         for(rg int i = 1 ; i <= n ; i++){
    71             scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    72             e[++tot] = seg(a, c, b, 1);
    73             X[tot] = a;
    74             e[++tot] = seg(a, c, d, -1);
    75             X[tot] = c;
    76         }
    77         sort(X + 1, X + tot + 1);
    78         sort(e + 1, e + tot + 1);
    79         int m = unique(X + 1, X + tot + 1) - X - 1;
    80         double res = 0;
    81         for(int i = 1 ; i <= tot ; i++){
    82             int l = lower_bound(X + 1, X + m + 1, e[i].l) - X;
    83             int r = lower_bound(X + 1, X + m + 1, e[i].r) - X - 1;
    84             //此处r少取一位,因为区间合并右端结果超出1,二者抵消 
    85             upd(l, r, 1, m, 1, e[i].tag);//
    86             res += t[1].len * (e[i + 1].h - e[i].h);
    87         }
    88         printf("Test case #%d
    ", cas++);
    89         printf("Total explored area: %.2f
    
    ", res);        
    90     }
    91     
    92     return 0;
    93 }

    ps:本随笔系原创作品,欢迎转载,请在文末注明原文链接

  • 相关阅读:
    算法笔记 --- Scale Sort
    算法笔记 --- String Rotation
    Css3动画缩放
    第一天
    SpringMVC_Controller中方法的返回值
    SpringMVC_url-pattern的写法
    SpringMVC_注释编写SpringMvc程序,RequestMapping常用属性,请求提交方式,请求携带参数
    SpringMVC_数据校验
    SpringMVC_类型转换器
    SpringMVC_异常处理的三种方式
  • 原文地址:https://www.cnblogs.com/ecustlegendn324/p/14243841.html
Copyright © 2020-2023  润新知