城市地平线

TimeLimit: 1 Second   MemoryLimit: 64 Megabyte

Totalsubmit: 10   Accepted: 1  

Description

在一条水平线上有N个建筑物,建筑物都是长方形的,且可以互相遮盖。给出每个建筑物的左右坐标值Ai,Bi以及每个建筑物的高度Hi,需要计算出这些建筑物总共覆盖的面积。

Input

第一行为建筑物的个数N(1<=N<=40000),第二行到第N+1行为每个建筑物的左右坐标值Ai,Bi(1<=Ai<Bi<=1000000000)和建筑物的高度Hi(1<=Hi<=1000000000)。

Output

总面积S。

Sample Input


5
1 5 10
2 6 30
3 7 20
4 6 15
5 10 5

Sample Output


165


#include <iostream>

using namespace std;

#define MAXN 40001


struct Line
{
        int x1, x2, height;
}line[MAXN];

struct Node
{
        int l, r, col;
        long long len;
};

int temp[MAXN * 2];
int ans[MAXN * 2];

bool cmp(Line a, Line b)
{
        return a.height > b.height;
}

class SGtree
{
        public:
        
        Node node[MAXN << 2];
        
        void Maketree(int i, int l, int r);
        
        void Update(int i, int x, int y, int val);
}tree;

void SGtree::Maketree(int i, int l, int r)
{
        node[i].l = l;
        node[i].r = r;
        int mid = (l + r) >> 1;
        
        if (l + 1 == r)
        {
                return ;
        }
        
        Maketree(i * 2, l, mid);
        Maketree(i * 2 + 1, mid, r);
}

void SGtree::Update(int i, int x, int y, int val)
{
        int l = node[i].l;
        int r = node[i].r;
        
        if (temp[l] == x && temp[r] == y)
        {
                node[i].col = 1;
                node[i].len = (temp[r] - temp[l]);
                
                return ;
        }
        
        if (node[i].col)
        {
                node[i * 2].col = node[i * 2 + 1].col = node[i].col;
                node[i].col = 0;
                node[i * 2].len = temp[node[i * 2].r] - temp[node[i * 2].l];
                node[i * 2 + 1].len = temp[node[i * 2 + 1].r] - temp[node[i * 2 + 1].l];
        }
        
        int mid = temp[(l + r) >> 1];
        
        if (y <= mid)
        {
                Update(i * 2, x, y, val);       
        }
        else if (x >= mid)
        {
                Update(i * 2 + 1, x, y, val);   
        }
        else
        {
                Update(i * 2, x, mid, val);
                Update(i * 2 + 1, mid, y, val); 
        }
        
        node[i].len = node[i * 2].len + node[i * 2 + 1].len;
}

void input()
{
        int n, x1, x2, height, cnt = 0;
        
        cin >> n;
        
        for (int i = 0; i < n; i++)
        {
                scanf("%d %d %d", &x1, &x2, &height);
                line[i].x1 = x1;
                ans[cnt++] = x1;
                line[i].x2 = x2;
                ans[cnt++] = x2;
                line[i].height = height;
        }
        
        sort(line, line + n, cmp);
        
        sort(ans, ans + cnt);
        
        int flag = -1;
        int total = -1;
        
        for (int i = 0; i < cnt; i++)
        {
                if (ans[i] != flag)
                {
                        flag = ans[i];
                        total++;
                }
                temp[total] = ans[i];
        }
        
        tree.Maketree(1, 0, total);
        
        long long sum = 0;
        
        for (int i = 0; i < n; i++)
        {
                tree.Update(1, line[i].x1, line[i].x2, 1);
                if (i != n - 1)
                {
                        sum += (long long)(line[i].height - line[i + 1].height) * tree.node[1].len;
                }
                else
                {
                        sum += (long long)line[i].height * tree.node[1].len;
                }
        }
        
        cout << sum << endl;
}

int main()
{
        input();
        return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值