UVA 1232 || LA 4108 (线段树)

题意:

按先后顺序告诉你每个长方形的左边界和右边界和高度, 求总覆盖度? 当前长方形的覆盖度为  左右的长度 使得他自己的高度最大。

思路:

很明显线段树。

我们直接按照输入顺序依次更新。

线段树里结点存的是线段,而不是点。

记录这个区间高度最大值,最小值。

当最大值小于等于h 时, 在递归更新。直到不能更新或者 区间全都比h小为止。

这样会TLE,要加个剪枝。

当前更新为h 时, 如果h 比最小值都小, 直接剪枝了。


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;


int T;
const int maxn = 100000 + 5;
struct node{
    int l,r;
    int setv;
    int Min, Max;
}nod[maxn<<2];

void build(int l,int r,int o){
    nod[o].l = l;
    nod[o].r = r;
    nod[o].setv = 0;
    nod[o].Min = 0;
    nod[o].Max = 0;
    if (l == r) {

        return;
    }
    int m = l + r >> 1;
    build(l, m, o << 1);
    build(m+1, r, o << 1 | 1);
}
void pushdown(int o){
    if (nod[o].setv){
        nod[o<<1].setv = nod[o<<1|1].setv = nod[o].setv;
        nod[o<<1].Min = nod[o<<1].Max = nod[o<<1|1].Min = nod[o<<1|1].Max = nod[o].setv;
        nod[o].setv = 0;
    }
}

void pushup(int o){
    int lson = o << 1;
    int rson = o << 1 | 1;
    nod[o].Min = min(nod[lson].Min, nod[rson].Min);
    nod[o].Max = max(nod[lson].Max, nod[rson].Max);
}
int update(int L,int R,int h,int l,int r,int o){
    if (nod[o].Min > h) return 0;
    if (L <= l && r <= R){
        if (l == r){
            if (nod[o].Max <= h){
                nod[o].Max = nod[o].Min = h;
                return 1;
            }
            else {
                return 0;
            }
        }
        else {
            if (nod[o].Max <= h){
                nod[o].Max = nod[o].Min = h;
                nod[o].setv = h;
                return r+1-l;
            }
            if (nod[o].Min > h) return 0;
        }
    }

    int m = l + r >> 1;
    pushdown(o);
    int ans = 0;
    if (m >= L){
        ans += update(L,R,h, l, m,o<<1);
    }
    if (m < R){

        ans += update(L,R,h,m+1,r,o<<1|1);
    }
    pushup(o);
    return ans;
}
int main(){
    while(scanf("%d",&T) == 1 && T){
        while(T--){
            int n;
            scanf("%d",&n);
            int ans = 0;
            build(1,100000-1,1);
            for (int i = 0; i < n; ++i){
                int l,r,h;
                scanf("%d %d %d",&l, &r, &h);
                ans += update(l, r-1, h, 1, 100000-1, 1);
            }
            printf("%d\n", ans);

        }
    }

    return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值