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