F - Finally, christmas! Gym - 102448F(扫描线)

The christmas spirit is taking over the city of Arcoverde! In honor of this special day, the mayor of this renowned metropolis decided to decorate all of the city’s front view. To do this, he asked his engineer friends Icaro and Cortizo how much it would cost.

It is known that the mayor likes to save as much money as possible. Therefore, Icaro and Cortizo need to find out what is the minimum area necessary to comprise the entire city’s front view.

Arcoverde is made only of rectangular buildings, in two dimensions, and all buildings were built on the same base height, as shown on the picture below.

Icaro and Cortizo were very tired, since they were also responsible for building the biggest christmas tree ever seen on Pernambuco, so they asked for your help.

Input
The first input line contains an integer N(1≤N≤105), indicating the number of buildings in Arcoverde. Then, N lines follow, each one containing three integers Li (0≤Li<109), Ri (Li<Ri≤109) and Hi (1≤Hi≤106), which are, respectively, the left X-coordinate, the right X-coordinate and the height of the i-th building.

Output
The output consists in a single integer number, which is the minimum area required to decorate the entire front view of Arcoverde.

Example
Input
6
2 6 9
9 14 11
12 20 6
17 25 20
23 31 14
29 36 18
Output
451

题意:
求这个图形的面积

思路:
一眼扫描线。线段树扫描线那就直接写。
对于扫描线之间的矩形面积,宽度可以之间相邻扫描线减法算出来,长度的话可以线段树维护覆盖了多少线。
但本题所有的扫描线都有共同起点(垂直x轴)且连续,所以直接用multiset维护最大值就得到宽度了。

扫描线直接排序

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 7;

struct Node {
    int x,y;
    bool operator < (const Node &rhs) const {
        if(x == rhs.x) return y > rhs.y;
        return x < rhs.x;
    }
}a[maxn];

multiset<int>s;

int main() {
    int n;scanf("%d",&n);
    for(int i = 1;i <= n;i++) {
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        a[i * 2 - 1].x = x;a[i * 2 - 1].y = z;
        a[i * 2].x = y;a[i * 2].y = -z;
    }
    
    sort(a + 1,a + 1 + n * 2);
    ll ans = 0;
    s.insert(-a[1].y);
    for(int i = 2;i <= n * 2;i++) {
        int h = -*s.begin();
        ans += 1ll * h * (a[i].x - a[i - 1].x);
        if(a[i].y < 0) {
            auto it = s.find(a[i].y);
            s.erase(it);
        } else {
            s.insert(-a[i].y);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

线段树写法

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 7;

map<int,int>mp;
int b[maxn];
struct Tree
{
    int l,r;
    int cover;
    ll sum;
}t[maxn << 4];

struct Node
{
    int x1,x2,y;
    int d;
    bool operator < (const Node &rhs)const
    {
        return y < rhs.y;
    }
}nodes[maxn];

int m1,m2;
void init()
{
    sort(b + 1,b + 1 + m2);
    b[++m1] = b[1];
    mp[b[1]] = 1;
    for(int i = 2;i <= m2;i++)
    {
        if(b[i] == b[i - 1])continue;
        b[++m1] = b[i];
        mp[b[i]] = m1;
    }
}

int bin(int x)
{
    return (int)(lower_bound(b + 1,b + 1 + m1,x) - b);
}

void build(int i,int l,int r)
{
    t[i].l = l;t[i].r = r;
    t[i].sum = 0;t[i].cover = 0;
    if(l == r)
    {
        return;
    }
    int m = (l + r) >> 1;
    build(i * 2,l,m);
    build(i * 2 + 1,m + 1,r);
    //    pushup(i);
}

void update(int i,int x,int y,int v)
{
    if(x <= t[i].l && t[i].r <= y)
    {
        t[i].cover += v;
        if(t[i].cover)
        {
            t[i].sum = b[t[i].r+1] - b[t[i].l];
        }
        else t[i].sum = t[i * 2].sum + t[i * 2 + 1].sum;
        return ;
    }
    int m = (t[i].l + t[i].r) >> 1;
    if(x <= m)update(i * 2,x,y,v);
    if(y > m)update(i * 2 + 1,x,y,v);
    t[i].sum = (t[i].cover ? b[t[i].r+1] - b[t[i].l] : t[i * 2].sum + t[i * 2 + 1].sum);
}

int main()
{
    int n;
    scanf("%d",&n);
    mp.clear();
    int cnt = 0;
    m1 = m2 = 0;
    for(int i = 1;i <= n;i++)
    {
        int x1,x2,y2;scanf("%d%d%d",&x1,&x2,&y2);
        int y1 = 0;
        nodes[++cnt].x1 = x1;nodes[cnt].x2 = x2;nodes[cnt].y = y1;nodes[cnt].d = 1;
        nodes[++cnt].x1 = x1;nodes[cnt].x2 = x2;nodes[cnt].y = y2;nodes[cnt].d = -1;
        b[++m2] = x1;b[++m2] = x2;
    }
    sort(nodes + 1,nodes + 1 + cnt);
    init();
    build(1,1,m1 - 1);
    
    ll ans = 0;
    for(int i = 1;i < cnt;i++)
    {
        int x1 = mp[nodes[i].x1];
        int x2 = mp[nodes[i].x2];
        int d = nodes[i].d;
        update(1,x1,x2 - 1,d);
        
        ans += 1ll * t[1].sum * (nodes[i + 1].y - nodes[i].y);
    }
    
    printf("%lld\n",ans);
    
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章