zoukankan      html  css  js  c++  java
  • 线段树扫描线(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 }
  • 相关阅读:
    SQL Server 幻读 的真实案例
    CSS hack 360浏览器 极速模式与兼容模式
    CS程序中XML编码Encode和解码Decode
    webbrowser 响应关闭事件
    asp.net Checkbox 绑定自定义属性
    企业库实现AOP的几种方法
    c# 自定义log4net过滤器
    SQL Server 并发死锁解决案例备忘
    c# 复制文件夹
    访问 iframe 内部控件方法
  • 原文地址:https://www.cnblogs.com/MingSD/p/8392240.html
Copyright © 2011-2022 走看看