zoukankan      html  css  js  c++  java
  • HDOJ 3265 Posters(扫描线 + 线段树 矩形面积的并)

    题意:

    给定N(N <= 50000)个中空的矩形纸片,求它们面积并。

    思路:

    1. 和前面一个矩形面积的并区别之处在于,这次是存在一个镂空的矩形,所以要切割成 4 个。

    2. 前面我尝试了一种不切割的方法,即只处理 4 根扫描线,结果证明这个思路是很麻烦的,因为扫描线是成对增加,成对消去,这样的话就制造了不必要的麻烦。

    3. 边界问题,越界问题,都要注意 sum[1] * (seg[i+1].h - seg[i].h) 这句话用 int 是会溢出的,所以当我改成 unsigned int 就 AC 了。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define lhs l, m, rt << 1
    #define rhs m + 1, r, rt << 1 | 1
    
    const int maxn = 200010;
    unsigned int sum[maxn << 2], cnt[maxn << 2];
    
    struct Segment {
        unsigned int l, r, h, v;
        Segment() { }
    
        Segment(int _l, int _r, int _h, int _v) : 
        l(_l), r(_r), h(_h), v(_v) { }
    
        bool operator < (const Segment& other) 
        { 
            if (h == other.h)
                return v > other.v;
            else
                return h < other.h; 
        }
    } seg[maxn << 1] ;
    
    void PushUp(int l, int r, int rt)
    {
        if (cnt[rt])
            sum[rt] = r - l + 1;
        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 main()
    {
        int n;
        while (scanf("%d", &n) && n)
        {
            int m = 0;
            int beg = 50000, end = 0;
            for (int i = 0; i < n; ++i)
            {
                int a, b, c, d;
                int a1, b1, c1, d1;
    
                scanf("%d %d %d %d", &a, &b, &c, &d);
                scanf("%d %d %d %d", &a1, &b1, &c1, &d1);
    
                beg = min(beg, a);
                end = max(end, c);
    
                seg[m++] = Segment(a, a1, b, 1);
                seg[m++] = Segment(a, a1, d, -1);
    
                seg[m++] = Segment(a1, c1, b, 1);
                seg[m++] = Segment(a1, c1, b1, -1);
    
                seg[m++] = Segment(a1, c1, d1, 1);
                seg[m++] = Segment(a1, c1, d, -1);
    
                seg[m++] = Segment(c1, c, b, 1);
                seg[m++] = Segment(c1, c, d, -1);
            }
            sort(seg, seg + m);
    
            memset(sum, 0, sizeof(sum));
            memset(cnt, 0, sizeof(cnt));
    
            __int64 ret = 0;
            for (int i = 0; i < m - 1; ++i)
            {
                if (seg[i].l < seg[i].r)
                    Update(seg[i].l, seg[i].r - 1, seg[i].v, beg, end - 1, 1);
                ret += (__int64)(sum[1] * (seg[i+1].h - seg[i].h));
            }
            printf("%I64d\n", ret);
        }
        return 0;
    }
  • 相关阅读:
    返回一个一维整数数组中最大子数组的和02
    软工作业04四则运算网页版
    所有子数组的和的最大值
    学习进度表(第五,六周)
    学习进度表(第四周)
    四则运算2的单元测试
    《构建之法》阅读笔记02
    软工作业03
    单元测试练习
    学习进度表(第三周)
  • 原文地址:https://www.cnblogs.com/kedebug/p/2890170.html
Copyright © 2011-2022 走看看