【2011集训队出题】Construct

Description:

  随着改革开放的深入推进……
  小T家要拆迁了……
  当对未来生活充满美好憧憬的小T看到拆迁协议书的时候,小T从一位大好的社会主义青年变成了绝望的钉子户。
  由于小T的家位于市中心,拆迁工作又难以进行,有关部门决定先把小T家用围栏围起来,以免影响市容。考虑到要建设资源节约型社会,他们希望所用的围栏长度越短越好,由于市中心寸土寸金,在围栏长度最短的情况下,围出的多边形面积越小越好。
  为了简化问题,我们约定,小T的家是一个多边形,并且每条边与坐标轴平行,围栏构成的也是多边形,每条边与坐标轴平行。
4≤n≤100000

题解:

周长就不用说了吧……

面积可以想象是把四个角缩起来。

具体的话,按y拍个序,从上到下扫,维护左右区间的最大值,倒着扫一遍,同样利用差分维护一下值,最后减去原矩形面积就是答案。

正确性读者可以自己画个图搞搞。

Code:

#include<cstdio>
#include<algorithm>
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
#define fd(i, x, y) for(ll i = x; i >= y; i --)
using namespace std;

const ll N = 1e5 + 5;

ll n, c, s;
struct node {
    ll x, y;
} a[N * 2];
ll up, down, left, right;

bool pd(node a, node b) {
    return a.y < b.y;
}

ll l, r;

int main() {
    scanf("%lld", &n);
    fo(i, 1, n) scanf("%lld %lld", &a[i].x, &a[i].y);
    sort(a + 1, a + n + 1, pd);
    up = right = -1e9; down = left = 1e9;
    fo(i, 1, n) {
        up = max(up, a[i].y); down = min(down, a[i].y);
        left = min(left, a[i].x); right = max(right, a[i].x);
    }
    c = (right - left + up - down) * 2;
    l = 1e9; r = -1e9;
    fo(i, 1, n) {
        if(i != 1 && a[i - 1].y != a[i].y)
            s += (r - l) * (a[i].y - a[i - 1].y);
        l = min(l, a[i].x);
        r = max(r, a[i].x);
    }
    l = 1e9; r = -1e9;
    fd(i, n, 1) {
        if(i != n && a[i + 1].y != a[i].y)
            s += (r - l) * (a[i + 1].y - a[i].y);
        l = min(l, a[i].x);
        r = max(r, a[i].x);
    }
    s -= (right - left) * (up - down);
    printf("%lld\n%lld\n", c, s);
}
相关文章
相关标签/搜索