zoukankan      html  css  js  c++  java
  • POJ 1151 Atlantis(扫描线 + 线段树 矩形面积的并)

    题意:

    给定 n 个矩形的坐标,求所有矩形所覆盖的面积。

    思路:

    1. 由于浮点数的存在并且坐标变化范围过大,需要对坐标进行离散化,这里线段树的叶子节点其实是一个区间

    2. 线段树每个节点(区间)需要有一个计数,代表的是整个区间是否存在一根或者多根扫描线。注意,这里指的是“整个区间”

    3. 如果这个区间的不存在完全覆盖的扫描线,则求其子区间扫描线的并。

     

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define lhs l, m, rt << 1
    #define rhs m + 1, r, rt << 1 | 1
    
    const int maxn = 2010;
    double sum[maxn << 2];
    int cnt[maxn << 2];
    double xcord[maxn];
    
    struct Segment {
        double l, r, h;
        int flag;
        Segment() { }
        Segment(double _l, double _r, double _h, int _f) 
            : l(_l), r(_r), h(_h), flag(_f) { }
        bool operator < (Segment& other) { return h < other.h; }
    } seg[maxn] ;
    
    void PushUp(int l, int r, int rt)
    {
        if (cnt[rt] > 0)
            sum[rt] = xcord[r+1] - xcord[l];
        else if (l == r)
            sum[rt] = 0;
        else
            sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    
    void Update(int beg, int end, int value, int l, int r, int rt)
    {
        if (beg <= l && r <= end)
        {
            cnt[rt] += value;
            PushUp(l, r, rt);
            return ;
        }
        int m = (l + r) >> 1;
        if (beg <= m)
            Update(beg, end, value, lhs);
        if (end > m)
            Update(beg, end, value, rhs);
        PushUp(l, r, rt);
    }
    
    int BinSearch(double key, double arr[], int size)
    {
        int l = 0, r = size - 1;
        while (l <= r)
        {
            int m = (l + r) >> 1;
            if (arr[m] == key)
                return m;
            else if (arr[m] > key)
                r = m - 1;
            else
                l = m + 1;
        }
        return -1;
    }
    
    int main()
    {
        int n, m;
        int cases = 0;
        while (~scanf("%d", &n) && n)
        {
            m = 0;
            for (int i = 0; i < n; ++i)
            {
                double a, b, c, d;
                scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
                xcord[m] = a;
                seg[m++] = Segment(a, c, b, 1);
                xcord[m] = c;
                seg[m++] = Segment(a, c, d, -1);
            }
            sort(xcord, xcord + m);
            sort(seg, seg + m);
    
            int mm = m;
            m = 1;
            for (int i = 1; i < mm; ++i)
                if (xcord[i] != xcord[i-1])
                    xcord[m++] = xcord[i];
    
            memset(cnt, 0, sizeof(cnt));
            memset(sum, 0, sizeof(sum));
    
            double ret = 0;
            for (int i = 0; i < mm - 1; ++i)
            {
                int l = BinSearch(seg[i].l, xcord, m);
                int r = BinSearch(seg[i].r, xcord, m) - 1;
                if (l <= r)
                    Update(l, r, seg[i].flag, 0, m - 1, 1);
                ret += sum[1] * (seg[i+1].h - seg[i].h);
            }
            printf("Test case #%d\nTotal explored area: %.2lf\n\n", ++cases, ret);
        }
        return 0;
    }
  • 相关阅读:
    2019-10-28-开源项目
    2018-8-10-win10-uwp-MetroLog-入门
    2018-5-20-C#-BBcode-转-Markdown
    2018-8-10-win10-UWP-序列化
    2018-2-13-win10-uwp-BadgeLogo-颜色
    2019-1-25-WPF-ListBox-的选择
    2019-1-5-Windows-的-Pen-协议
    android studio打印
    Java 基本数据类型
    FreeRTOS 任务通知模拟计数型信号量
  • 原文地址:https://www.cnblogs.com/kedebug/p/2888850.html
Copyright © 2011-2022 走看看