UVaLive 4108 - SKYLINE (线段树)

UVALive - 4108
Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

[]   [Go Back]   [Status]  

Description

Download as PDF

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, $ \langle$b1,b2,..., bn$ \rangle$ , 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 kbuildings (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 buildingbi is described by three positive integers, separated by spaces, namely, li , ri and hi , where li and rj(0 < li < ri$ \le$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

Source

[]   [Go Back]   [Status]  




题意:

要在地平线上依次修建n座建筑物,建筑物的修建顺序按照从后往前的顺序,因此新建建筑物可能会挡住一部分老建筑物。

修建完一座后统计他有多长的部分是最高的(可以并列最高)。求所有建筑物该长度的总和。



之前看过这个题,但是没有思路,当时的想法是离线按照高度处理,但是这有复杂度太高。

今天再看这个题的时候突然就想到了做法

直接维护区间的建筑物高度,比如

初始的时候全部区间都为高度为0,有两座建筑物:

5 11 3 结果是 [5, 10](把区间变成点,[x, x+1]用区间的左端点x表示)高度为3

1 10 1 结果是[1, 4]高度为1,[5, 10]高度为3。

 也就是 set [L, R]为v的时候,只有当区间的setv小于v的才set

这样答案就是[L, R]中setv比v大的区间长度

然后这样交上去TLE了,然后一想这样一次操作复杂度可达到O(n*4)(线段树节点总数),因为当1-n的高度分别为1-n的时候就会出现这种极端情况。

然后加了一个minv维护区间的最小值,如果最小值都比当前高度大,那么这个区间肯定会遮挡当前建筑物。就不用递归下去了




#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 100000 + 20;
const int maxo = maxn * 4;

int setv[maxo];
int minv[maxo];

void pushDown(int o) {
    if(setv[o] != -1) {
        minv[o<<1] = setv[o<<1] = setv[o<<1|1] = setv[o];
        setv[o] = -1;
    }
}

void pushUp(int o) {
    minv[o] = min(minv[o*2], minv[o*2+1]);
}

int ql, qr, qv, _qans;
void update(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        if(setv[o] != -1) {
            if(setv[o] > qv) {
                _qans += R - L + 1;
            } else {
                setv[o] = qv;
            }
            minv[o] = setv[o];
            return ;
        }
        if(minv[o] > qv) {
            _qans += R - L + 1;
            return ;
        }
    }
    pushDown(o);
    int M = L + (R-L) / 2;
    if(ql <= M) update(o<<1, L, M);
    if(M < qr) update(o<<1|1, M+1, R);
    pushUp(o);
}

int qls[maxn], qrs[maxn], qvs[maxn];

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        int n;
        int maxL = 0;
        memset(setv, -1, sizeof(setv));
        memset(minv, 0, sizeof(minv));
        setv[1] = 0;
        scanf("%d", &n);
        for(int i=0; i<n; i++) {
            scanf("%d%d%d", &qls[i], &qrs[i], &qvs[i]);
            maxL = max(maxL, qrs[i]);
        }
        maxL = maxL + 2;
        LL ans = 0;
        for(int i=0; i<n; i++) {
            _qans = 0;
            ql = qls[i], qr = qrs[i] - 1, qv = qvs[i];
            update(1, 1, maxL);
            ans += qrs[i] - qls[i] - _qans;
        }
        P64I(ans);
    }
    scanf("%*d");

    return 0;
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值