EOJ 3216 都市地平线

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/fwq990720/article/details/79240472

题目简介


约翰带着奶牛去都市观光。在落日的余晖里,他们看到了一幢接一幢的摩天高楼的轮廓在地平线上形成美丽的图案。以地平线为 X 轴,每幢高楼的轮廓是一个位于地平线上的矩形,彼此间可能有重叠的部分。奶牛一共看到了 N 幢高楼,第 i 幢楼的高度是 Hi,两条边界轮廓在地平线上的坐标是 Ai 到 Bi。请帮助奶牛们计算一下,所有摩天高楼的轮廓覆盖的总面积是多少。

说明


乍看之下像计算几何,实际上这题除了线段树扫描线以外还有很多方法……比如splay、优先队列、并查集等等。
这里偷懒用了multiset维护高度。先按横坐标降序排序,然后从左向右扫,dir判断当前边是矩形的左还是右。如果是左边就加入multiset,是右边就删除掉,那么这一块的矩形面积就是S=hmaxΔx。求和即可。

#include <bits/stdc++.h>
using namespace std;
#define maxn 80005

typedef long long ll;
struct seg {
    int x, hi, dir;
    seg() {}
    seg(int a, int b, int c) : x(a), hi(b), dir(c) {}
    bool operator < (const seg& rhs) const
    {
        return x < rhs.x;
    }
} s[maxn];

int main()
{
    int n, a, b, hi, cnt = 0;
    ll ans = 0;
    multiset<int, greater<int> > ms;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a >> b >> hi;
        s[cnt++] = seg(a, hi, 1);
        s[cnt++] = seg(b, hi, 0);
    }
    sort(s, s + cnt);
    ms.insert(0);
    for (int i = 0; i < cnt - 1; ++i) {
        if (s[i].dir) ms.insert(s[i].hi);
        else {
            multiset<int, greater<int> >::iterator it = ms.find(s[i].hi);
            ms.erase(it);
        }
        ans += (ll)(*ms.begin()) * (s[i + 1].x - s[i].x);
    }
    printf("%lld\n", ans);
}
展开阅读全文

没有更多推荐了,返回首页