USACO 5.5.1Picture

Posted albertxwz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO 5.5.1Picture相关的知识,希望对你有一定的参考价值。

题目大意

  给出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\n", ans);
    return 0;
}

 

以上是关于USACO 5.5.1Picture的主要内容,如果未能解决你的问题,请参考以下文章

USACO5.5 矩形周长 Picture | 扫描线 + 线段树

POJ 1177 Picture

[USACO5.5] 矩形周长Picture

[USACO5.5]矩形周长Picture[扫描线+线段树]

luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树

luogu1856 [USACO5.5]矩形周长Picture