1232 - SKYLINE

The skyline of Singapore as viewed from the Marina Promenade (shown on the left) is one of the iconic scenes of Singapore. Country X would also like to create an iconic skyline, and it has put up a call for proposals. Each submitted proposal is a description of a proposed skyline and one of the metrics that country X will use to evaluate a proposed skyline is the amount of overlap in the proposed sky-line.

\epsfbox{p4108a.eps}
As the assistant to the chair of the skyline evaluation committee, you have been tasked with determining the amount of overlap in each proposal. Each proposal is a sequence of buildings, b1, b2,…, bn , where a building is specified by its left and right endpoint and its height. The buildings are specified in back to front order, in other words a building which appears later in the sequence appears in front of a building which appears earlier in the sequence.

The skyline formed by the first k buildings is the union of the rectangles of the first k buildings (see Figure 4). The overlap of a building, bi , is defined as the total horizontal length of the parts of bi , whose height is greater than or equal to the skyline behind it. This is equivalent to the total horizontal length of parts of the skyline behind bi which has a height that is less than or equal to hi , where hi is the height of building bi . You may assume that initially the skyline has height zero everywhere.

Input

The input consists of a line containing the number c of datasets, followed by c datasets, followed by a line containing the number `0’.

The first line of each dataset consists of a single positive integer, n (0 < n < 100000) , which is the number of buildings in the proposal. The following n lines of each dataset each contains a description of a single building. The i -th line is a description of building bi . Each building bi is described by three positive integers, separated by spaces, namely, li , ri and hi , where li and rj (0 < li < ri 100000) represents the left and right end point of the building and hi represents the height of the building.

\epsfbox{p4108b.eps}
Output

The output consists of one line for each dataset. The c -th line contains one single integer, representing the amount of overlap in the proposal for dataset c . You may assume that the amount of overlap for each dataset is at most 2000000.

Note: In this test case, the overlap of building b1 , b2 and b3 are 6, 4 and 4 respectively. Figure 4 shows how to compute the overlap of building b3 . The grey area represents the skyline formed by b1 and b2 and the black rectangle represents b3 . As shown in the figure, the length of the skyline covered by b3 is from position 3 to position 5 and from position 11 to position 13, therefore the overlap of b3 is 4.

Sample Input

1
3
5 11 3
1 10 1
3 13 2
0
Sample Output

14

我有话说:
这道题和直观的数字加减求和的线段树不同,需要一定的思想转化。因为考虑美歌建筑物的左端和右端未知,所以应当先估算一定的范围建树。并且对于一个建筑用结构体保存。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;
const int maxn = 100000+5;
const int INF=100000000;
typedef long long LL;
struct Node{
    int l,r,h,sign;//sign表示左右高度是否相同
    void init(int l,int r,int h,int sign){
        this->l=l;
        this->r=r;
        this->h=h;
        this->sign=sign;
    }
}node[maxn*4];
int pushdown(int u){//向下传递标记
    int lc=u*2,rc=u*2+1;
    node[lc].sign=node[rc].sign=1;
    node[lc].h=node[rc].h=node[u].h;
    node[u].sign=0;//清空标记
    node[u].h=0;
}
void pushup(int u){
    int lc=u*2,rc=u*2+1;
    node[u].l=node[lc].l;
    node[u].r=node[rc].r;
    if(node[lc].sign&&node[rc].sign&&node[lc].h==node[rc].h){
        node[u].sign=1;
        node[u].h=node[lc].h;
        }else node[u].sign=node[u].h=0;//不平的一段没法计算,分治
}
int build(int u,int l,int r){
    if(l==r)node[u].init(l,r,0,1);
    else{
        int m=(l+r)/2;
        int lc=u*2,rc=u*2+1;
        build(lc,l,m);
        build(rc,m+1,r);
        pushup(u);
    }
}
int update(int u,int l,int r,int h){
    if(node[u].sign&&node[u].h>h)return 0;//这段区间里面的覆盖高度应该要一样否则必须细分
    if(node[u].l>=l&&node[u].r<=r&&node[u].sign){//刚才已经比较过高度
        node[u].h=h;
        return node[u].r-node[u].l+1;
    }
    int ret=0;
    int m=(node[u].l+node[u].r)/2;
    int lc=u*2,rc=u*2+1;
    if(node[u].sign)pushdown(u);//向下传递标记。
    if(l<=m)ret+=update(lc,l,r,h);
    if(r>m)ret+=update(rc,l,r,h);
    pushup(u);
    return ret;
}
int main()
{
    int T;
    int n,l,r,h,ans;
    scanf("%d",&T);
    while(T--){
        build(1,1,maxn);
        scanf("%d",&n);
        ans=0;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&l,&r,&h);
            ans+=update(1,l+1,r,h);
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值