• 【USACO 5.5.1】Picture


    题目大意

      给出N个矩形重叠后的图形,要求出重叠后图形的轮廓线长。

    题解

      参照1999年国家集训队陈宏的论文《数据结构的选择与算法效率——从IOI98试题PICTURE谈起》。

      里面说得很清楚,这里不细讲。

      就是把PICTURE抽象出一个统计区间个数的模型。简单粗暴地用线段树+离散化上了。

    代码

    /*
    TASK:picture
    LANG:C++
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    const int MAXN = 5005;
    const int RANGE = 10001;
    
    struct Matrix
    {
        int x[2], y[2];
    }matrix[MAXN];
    
    struct Line
    {
        int h, l, r, delx;
        
        bool operator < (const Line &b) const
        {
            return h < b.h;
        }
        
    }line[MAXN << 1];
    
    int n, ans, nl, xcnt, ycnt;
    int leftv[RANGE << 5], rightv[RANGE << 5], lazytag[RANGE << 5], minv[RANGE << 5], maxv[RANGE << 5];
    
    void maintain(int o)
    {
        int lc = o << 1, rc = lc + 1;
        leftv[o] = leftv[lc];
        rightv[o] = rightv[rc];
        minv[o] = min(minv[lc], minv[rc]);
        maxv[o] = max(maxv[lc], maxv[rc]);
    }
    
    void pushdown(int o)
    {
        int lc = o << 1, rc = lc + 1;
        if (lazytag[o])
        {
            minv[lc] += lazytag[o];
            maxv[lc] += lazytag[o];
            minv[rc] += lazytag[o];
            maxv[rc] += lazytag[o];
            leftv[lc] += lazytag[o];
            leftv[rc] += lazytag[o];
            rightv[lc] += lazytag[o];
            rightv[rc] += lazytag[o];
            lazytag[lc] += lazytag[o];
            lazytag[rc] += lazytag[o];
            lazytag[o] = 0;
        }
    }
    
    void update(int o, int L, int R, int y1, int y2, int dx)
    {
        if (y1 <= L && R <= y2)
        {
            leftv[o] += dx;
            rightv[o] += dx;
            minv[o] += dx;
            maxv[o] += dx;
            lazytag[o] += dx;
            return;
        }
        pushdown(o);
        int mid = (L + R) >> 1;
        int lc = o << 1, rc = lc + 1;
        if (mid >= y1) update(lc, L, mid, y1, y2, dx);
        if (mid + 1 <= y2) update(rc, mid + 1, R, y1, y2, dx);
        maintain(o);
    }
    
    int query(int o, int L, int R)
    {
        if (minv[o] > 0) return 1;
        if (maxv[o] == 0) return 0;
        pushdown(o);
        int mid = (L + R) >> 1;
        int lc = o << 1, rc = lc + 1;
        int a = query(lc, L, mid), b = query(rc, mid + 1, R);
        if (rightv[lc] && leftv[rc]) return a + b - 1;
        else return a + b;
    }
    
    void work(int cur)
    {
        nl = 0;
        for (int i = 0; i < n; ++i)
            if (cur == 0)
            {
                line[nl].h = matrix[i].x[0];
                line[nl].l = matrix[i].y[0];
                line[nl].r = matrix[i].y[1];
                line[nl++].delx = 1;
                
                line[nl].h = matrix[i].x[1];
                line[nl].l = matrix[i].y[0];
                line[nl].r = matrix[i].y[1];
                line[nl++].delx = -1;
            }
            else
            {
                line[nl].h = matrix[i].y[0];
                line[nl].l = matrix[i].x[0];
                line[nl].r = matrix[i].x[1];
                line[nl++].delx = 1;
                
                line[nl].h = matrix[i].y[1];
                line[nl].l = matrix[i].x[0];
                line[nl].r = matrix[i].x[1];
                line[nl++].delx = -1;
            }
        
        sort(line, line + nl);
        
        memset(leftv, 0, sizeof(leftv));
        memset(rightv, 0, sizeof(rightv));
        memset(maxv, 0, sizeof(maxv));
        memset(minv, 0, sizeof(minv));
        memset(lazytag, 0, sizeof(lazytag));
        memset(minv, 0, sizeof(minv));
        for (int i = 0; i < nl - 1; ++i)
        {
            update(1, 1, 4 * RANGE, 2 * (line[i].l + RANGE - 1), 2 * (line[i].r + RANGE - 1), line[i].delx);
            ans += query(1, 1, 4 * RANGE) * 2 * (line[i + 1].h - line[i].h);
        }
    }
    
    int main()
    {
        freopen("picture.in", "r", stdin);
        freopen("picture.out", "w", stdout);
        scanf("%d", &n);
        xcnt = ycnt = 0;
        for (int i = 0; i < n; ++i)
            scanf("%d%d%d%d", &matrix[i].x[0], &matrix[i].y[0], &matrix[i].x[1], &matrix[i].y[1]);
        ans = 0;
        work(0);
        work(1);
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    hihoCoder #1176 : 欧拉路·一 (简单)
    228 Summary Ranges 汇总区间
    227 Basic Calculator II 基本计算器II
    226 Invert Binary Tree 翻转二叉树
    225 Implement Stack using Queues 队列实现栈
    224 Basic Calculator 基本计算器
    223 Rectangle Area 矩形面积
    222 Count Complete Tree Nodes 完全二叉树的节点个数
    221 Maximal Square 最大正方形
    220 Contains Duplicate III 存在重复 III
  • 原文地址:https://www.cnblogs.com/albert7xie/p/5325129.html
Copyright © 2020-2023  润新知