Uva 1232 - SKYLINE ( 线段树 + 区间更新 )

 

Uva 1232 SKYLINE (线段树 + 区间更新)

题意: 按照顺序在地面上建造放在,每个房子的高度为h,操作 l r h 表示 在(l,r] 区间建立一个高度为h的房子。
统计每次建立完房子之后的overlap值之和

overlap值表示[ 修完一座房子之后,统计它在多长的部分是最高的(可以和其他房子并列高) ]
如样例图,按照灰、黒。白的顺序建立房子
ans = (11-5) + (5-1) + (5-3) + (13-11) = 6 + 4 + 4 = 14

Uva 1232 - SKYLINE ( 线段树 + 区间更新 )


分析: 一开始一直想不明白如何向下传递,这里实际上Pushdown操作就是普通的懒惰标记
PushUp操作用来想上更新minh和maxh

这里需要维护至少两个域 一个是 房子的高度setv 一个是maxh,区间内房子的最大高度。
不过从别人的博客看到还有一个优化,就是再开一个minh域,存放区间内房子的最小高度,
很显然,如果新建立的房子高度比该区间的minh还小,就不需要更新了。
结果用ans进行累加即可,这里要注意,线段是连续的,但是所以区间(l,r]想当于[l+1,r]
update的时候注意下,还有就是求ans的时候记得+1

//#define BUG

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <map>

#include <vector>

#include <list>

#include <queue>

#include <ctime>

#include <iostream>

#include <cmath>

#include <set>

#include <string>

using namespace std;

typedef long long LL;

typedef unsigned long long ULL;

#define INF                 0x7fffffff

#define MAX                 0x3f3f3f3f



#define CLR( a, b )         memset( a, b, sizeof(a) )

#define REP( i, a, b )      for( int i = (a); i < (b); ++i )

#define FOR( i, a, b )      for( int i = (a); i <=(b); ++i )

#define FOD( i, a, b )      for( int i = (a); i >=(b); --i )



#define MID                 ( l + r ) >> 1

#define lson                l, m, o << 1

#define rson                m + 1, r, o << 1 | 1

#define ls                  o << 1

#define rs                  o << 1 | 1

#define MAXN                100010



struct SegTree

{

    int l, r;

    int setv, maxh, minh;



}tree[MAXN << 2];

int ans;



void PushUp( int o )

{

    tree[o].maxh = max( tree[ls].maxh , tree[rs].maxh );

    tree[o].minh = min( tree[ls].minh , tree[rs].minh );

}



void PushDown( int o )

{

    if( tree[o].setv != -1 )        //三个标记往下传

    {

        tree[ls].setv = tree[rs].setv = tree[o].setv;

        tree[ls].maxh = tree[rs].maxh = tree[o].maxh;

        tree[ls].minh = tree[rs].minh = tree[o].minh;

        tree[o].setv = -1;

    }

}



void Build( int l, int r, int o )

{

    tree[o].l = l, tree[o].r = r;

    tree[o].setv = tree[o].maxh = tree[o].minh = 0;

    if( l == r )

        return;

    int m = MID;

    Build( lson );

    Build( rson );

}





void Update( int L, int R, int c, int o )

{

    if( tree[o].minh > c )    return;

    if( tree[o].l == L && tree[o].r == R )

    {

        if( tree[o].maxh <= c )

        {

            tree[o].setv = tree[o].maxh = tree[o].minh = c;

            ans += R - L + 1;

            return;

        }

        if( L == R )  return;

    }



    PushDown( o );

    int m = ( tree[o].l + tree[o].r ) >> 1;

    if( R <= m )  Update( L, R, c, ls );

    else if( L >  m )  Update( L, R, c, rs );

    else

    {

        Update( L, m, c, ls );

        Update( m + 1, R, c, rs );

    }

    PushUp( o );

}



void Orz()

{

    #ifdef  BUG

        freopen("in.txt","r",stdin);

    #endif

    int cas, n;

    int l, r, c;

    while( ~scanf( "%d", &cas ) && cas )

    {

        while( cas-- )

        {

            scanf( "%d", &n );

            Build(1,MAXN,1);

            ans = 0;

            while( n-- )

            {

                scanf( "%d %d %d", &l, & r, &c );

                Update( l + 1, r, c, 1);

            }

            printf( "%d\n", ans );

        }

    }

}



int main()

{

    Orz();

    return 0;

}
代码君

 

 

 








你可能感兴趣的:(线段树)