[UVA][線段樹] 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.
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.
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
先說說題目, 建築物從海岸線開始退, 每個建築物可以當作一個長方形平行海岸,
而每個建築物都有其高度, 如果被前面的建築物遮蔽的區塊, 則在這建築物中的一小段區間
是無法看到海岸的, 計算所有建築物可以看到海岸的區間長度總和。
雖然說是線段樹, 但操作並不是 O(logn), 跟輸入有關, 不過能快就快了,
記錄每個區間的最大高度與最小高度, 最大高度用來判定能不能計算這個區間可以被看到,
而最小高度則用來判定這個區間有沒有機會被這個建築物的區間看到海岸,
因此最後會簡單地想到, 一個線段樹的區間如果被 matched, 不一定就這麼結束,
會直到找到可以更新的區間並加以計算。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct Node {
int mx, mn, label;
};
Node ST[(1<<18)+1];
long long ret;
void update(int k) {
ST[k].mx = max(ST[k<<1].mx, ST[k<<1|1].mx);
ST[k].mn = min(ST[k<<1].mn, ST[k<<1|1].mn);
}
void downdate(int k) {
if(ST[k].label) {
ST[k<<1].mx = ST[k<<1].mn = ST[k<<1].label = ST[k].label;
ST[k<<1|1].mx = ST[k<<1|1].mn = ST[k<<1|1].label = ST[k].label;
ST[k].label = 0;
}
}
void modify(int k, int l, int r, int &ql, int &qr, int h) {
if(l > r)
return;
if(l != r)
downdate(k);
if(ST[k].mn > h)
return;
if(ql <= l && r <= qr) {
if(h >= ST[k].mx) {
ret += r-l+1;
ST[k].mx = ST[k].mn = ST[k].label = h;
return;
}
// still update sub-interval
}
int m = (l+r)>>1;
if(ql > m)
modify(k<<1|1, m+1, r, ql, qr, h);
else if(qr <= m)
modify(k<<1, l, m, ql, qr, h);
else {
modify(k<<1, l, m, ql, qr, h);
modify(k<<1|1, m+1, r, ql, qr, h);
}
update(k);
}
int main() {
int testcase, n, x, y, h;
int i, j;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d", &n);
memset(ST, 0, sizeof(ST));
ret = 0;
for(i = 0; i < n; i++) {
scanf("%d %d %d", &x, &y, &h);
y--;
modify(1, 1, 100000, x, y, h);
}
printf("%lld\n", ret);
}
return 0;
}