首页 > 代码库 > Uva 1232 - SKYLINE ( 线段树 + 区间更新 )

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


分析: 一开始一直想不明白如何向下传递,这里实际上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                100010struct 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;}
代码君

 

 

 








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