• 线段树扫描线(1---算矩形的总面积)


    http://acm.hdu.edu.cn/showproblem.php?pid=1542

    线段树扫描线又是线段树的一种特殊的跑法

    先将X坐标离散化 

    然后将扫描线按照高度从矮到高进行更新

    每次遇到下边的时候就在对应的左区间右区间所对应的cnt值++

    每次遇到上边的时候就在对应的左区间右区间所对应的cnt值--

    然后在PushUp  如果 cnt>0 那么说明整个区间内的线都是有效的 这个时候只需要计算整个区间的长度

    如果cnt == 0 并且 l == r 那么就说明这个区间内是没有有效的线 

    如果cnt == 0 并且 l != r 那么这个区间内的有效线段就是下属区间的有效线段之和

    至于访问到下面的时候为什么不需要将cnt标记下推 

    原因有2个: 1.无论下边的节点是2 还是3 只要这个节点的cnt>0  那么就是整个区间的线段都是有效线段 所以不需要具体到将cnt标记下推来区分左子叶的cnt值是1 右节点的cnt值是2 还是3, 效果都是一样的。

    2:因为每一条下边长的扫描线都会有一条完全对应的上变成的扫描线来抵消 所以 这个影响会在后面抵消。

    最后每次跑扫描线的时候只需要将 sum[1]*(高度差)累加起来就是答案了。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<iomanip>
     4 #define lson l,m,rt<<1
     5 #define rson m+1,r,rt<<1|1
     6 using namespace std;
     7 const int N = 1e3;
     8 struct Node
     9 {
    10     double l, r, h;
    11     int d;
    12     bool operator < (const Node & x) const
    13     {
    14         return h < x.h;
    15     }
    16 }A[N];
    17 double X[N], sum[N];
    18 int cnt[N];
    19 void Build(int l, int r, int rt)
    20 {
    21     cnt[rt] = 0, sum[rt] = 0.0;
    22     if(l == r) return ;
    23     int m = l+r >> 1;
    24     Build(lson);
    25     Build(rson);
    26 }
    27 void PushUp(int l, int r, int rt)
    28 {
    29     if(cnt[rt])
    30     {
    31         sum[rt] = X[r] - X[l-1];
    32     }
    33     else if(l == r) sum[rt] = 0.0;
    34     else sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    35 }
    36 void Revise(int L, int R, int C, int l, int r, int rt)
    37 {
    38     if(L <= l && r <= R)
    39     {
    40         cnt[rt] += C;
    41         PushUp(l,r,rt);
    42         return ;
    43     }
    44     int m = l+r >> 1;
    45     if(L <= m) Revise(L,R,C,lson);
    46     if(m < R) Revise(L,R,C,rson);
    47     PushUp(l,r,rt);
    48 }
    49 void Add(double l, double r, double h, int d, int i)
    50 {
    51     A[i].l = l; A[i].h = h;
    52     A[i].r = r; A[i].d = d;
    53 }
    54 int main()
    55 {
    56     ios::sync_with_stdio(false);
    57     cin.tie(0);
    58     cout.tie(0);
    59     int Case = 0, n;
    60     while(cin >> n, n)
    61     {
    62         int k = 0;
    63         double x1, y1, x2, y2;
    64         for(int i = 1; i <= n; i++)
    65         {
    66             cin >> x1 >> y1 >> x2 >> y2;
    67             Add(x1,x2,y1,1,k);
    68             X[k++] = x1;
    69             Add(x1,x2,y2,-1,k);
    70             X[k++] = x2;
    71         }
    72         sort(X,X+k);
    73         sort(A,A+k);
    74         int pos = 1;
    75         for(int i = 1; i < k; i++)
    76         {
    77             if(X[i] != X[i-1])
    78                 X[pos++] = X[i];
    79         }
    80         Build(1,pos,1);
    81         double ans = 0;
    82         for(int i = 0; i < k-1; i++)
    83         {
    84             int l = lower_bound(X,X+pos,A[i].l) - X;
    85             int r = lower_bound(X,X+pos,A[i].r) - X;
    86             Revise(l+1,r,A[i].d,1,pos,1);
    87             ans += (A[i+1].h - A[i].h) * sum[1];
    88         }
    89         cout << "Test case #" << ++Case << endl;
    90         cout << "Total explored area: " << fixed
    91              << setprecision(2) << ans << endl << endl;
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    JDBC
    Linux下的tar压缩解压缩命令详解
    Shell编程介绍
    SSH服务认证类型介绍
    SSH介绍及连接原理
    MySQL引擎之innodb介绍及特点
    myisam 存储引擎介绍及特点
    maven项目依赖中报错Plugin ‘org.apache.maven.plugins:maven-compiler-plugin:’ not found
    List调用add方法报错java.lang.UnsupportedOperationException
    C基础
  • 原文地址:https://www.cnblogs.com/MingSD/p/8392240.html
Copyright © 2020-2023  润新知