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;
}

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