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 }
  • 相关阅读:
    [转载]写作经验谈--如何写一本书?
    决定写一本书
    c中自定义函数通过sizeof来输出数组的长度为何不正确?【原创】
    [转]关于PHP的漏洞以及如何防止PHP漏洞?
    [转]PHP安全之防止你的源代码或重要配置信息暴露在外
    PHPUnit 单元测试框架(鸡肋)
    [转]避免PHP-FPM内存泄漏导致内存耗尽
    [转]PHP ffmpeg截取视频指定帧为图片,获取rotation信息并旋转
    ThinkPHP 缓存 以及Zend OPCache提升PHP性能
    简单测漏 语句
  • 原文地址:https://www.cnblogs.com/MingSD/p/8392240.html
Copyright © 2011-2022 走看看