leetcode:699. 掉落的方块

题目来源

题目描述

在这里插入图片描述

class Solution {
public:
    vector<int> fallingSquares(vector<vector<int>>& positions) {

    }
};

题目解析

这题主要需要解决两个问题:

  • 当每次落下来一个方块的时候,我们需要判断它会落在哪个格子的上面。
  • 由于格子能堆叠,因此需要能知道当前格子的真实高度。

格子按照顺序落下来,大致有三种可能

在这里插入图片描述

假设 p o s i t i o n s [ i ] = [ l e f t i , s i d e L e n g t h i ] positions[i] = [left_i, sideLength_i] positions[i]=[lefti,sideLengthi]落下来,因为它是一个正方形,其边长为 s i d e L e n g t h i sideLength_i sideLengthi,所以它的右边界为 r i g h t i = l e f t i + s i d e L e n g t h i right_i = left_i + sideLength_i righti=lefti+sideLengthi。也就是说它会落在区间 [ l e f t i , r i g h t i ] [left_i,right_i ] [leftirighti]。问题是这个区间的高度会是多少呢?

有上面知道,落下来有三种可能:

  • 之前底下完全不没有任何方块,所以要将 [ l e f t i , r i g h t i ] [left_i,right_i ] [leftirighti]区间的高度修改为 s i d e L e n g t h i sideLength_i sideLengthi
  • 贴着一个方块落下来,所以要将 [ l e f t i , r i g h t i ] [left_i,right_i ] [leftirighti]区间的高度修改为 s i d e L e n g t h i sideLength_i sideLengthi
  • 底下有一个方块,所以要将 [ l e f t i , r i g h t i ] [left_i,right_i ] [leftirighti]区间的高度修改为 b e f o r e H e i g h t + s i d e L e n g t h i beforeHeight + sideLength_i beforeHeight+sideLengthi

最终返回所有区间上的最大高度。

我们并不需要关心方块内部是怎么放的,只需要看某个区间上的高度就可以了。

在这里插入图片描述

所以,这道题可以转换为如下三个问题:

  • 修改指定区间上的高度为某个值
  • 查询所有区间上的最大高度

问题是放方块贴边落下来时怎么修改高度呢?

  • 很简单,每次修改高度时只修改 [ l e f t i , r i g h t i ) [left_i,right_i ) [leftirighti)即可,也就是 [ l e f t i , r i g h t i − 1 ] [left_i,right_i - 1] [leftirighti1]
class Solution {
    class SegmentTree{
        std::vector<int> m_height;
        std::vector<int> m_change;
        std::vector<bool> m_update;

        void pushUp(int idx){
            m_height[idx] = std::max(m_height[idx << 1], m_height[idx << 1 | 1]);
        }

        // l_node表示左子树元素结点个数,r_node表示右子树结点个数
        void pushDown(int idx, int l_node, int r_node){
            if(m_update[idx]){
                m_height[idx << 1] = m_change[idx];
                m_height[idx << 1 | 1] = m_change[idx];
                m_change[idx << 1] = m_change[idx];
                m_change[idx << 1 | 1] = m_change[idx];
                m_update[idx << 1] = true;
                m_update[idx << 1 | 1] = true;
                m_update[idx] = false;
            }
        }
    public:
        SegmentTree(int size){
            int N = size << 2;
            m_height.resize(N);
            m_change.resize(N);
            m_update.resize(N);
        }

        void update(int L, int R, int C, int l, int r, int idx){
            if(L <= l && r <= R){
                m_height[idx] = C;
                m_change[idx] = C;
                m_update[idx] = true;
                return;
            }

            int mid = (l + r) >> 1;
            int l_node = mid - l + 1, r_node = r - mid;
            pushDown(idx, l_node, r_node);
            if(L <= mid){
                update(L, R, C, l, mid, idx << 1);
            }
            if(mid + 1 <= R){
                update(L, R, C, mid + 1, r, idx << 1 | 1);
            }
            pushUp(idx);
        }

        int query(int L, int R, int l, int r, int idx){
            if(L <= l && r <= R){
                return m_height[idx];
            }
            int mid = (l + r) >> 1;
            int l_node = mid - l + 1, r_node = r - mid;
            pushDown(idx, l_node, r_node);
            int left = 0, right = 0;
            if(L <= mid){
                left = query(L, R, l, mid, idx << 1);
            }
            if(mid + 1 <= R){
                right = query(L, R,  mid + 1, r, idx << 1 | 1);
            }
            return std::max(left, right);
        }
    };

    std::map<int, int> index(vector<vector<int>>& positions){
        std::set<int> pos;
        for(auto arr : positions){
            pos.insert(arr[0]);
            pos.insert(arr[0] + arr[1] - 1);
        }

        std::map<int, int> map;
        int cnt = 0;
        for(auto idx : pos){
            map.insert({idx, ++cnt});
        }
        return map;
    }
public:
    vector<int> fallingSquares(vector<vector<int>>& positions) {
        std::map<int, int> map = index(positions);
        int N = map.size();
        SegmentTree seg(N);
        int max = 0;
        std:vector<int> res;
        // 每落一个正方形,收集一下,所有东西组成的图像,最高高度是什么
        for(auto arr : positions){
            int L = map[arr[0]], R = map[arr[1] + arr[0] - 1];
            int height = seg.query(L, R, 1, N, 1) + arr[1];  //计算出本区间的高度: 先查询本区间的高度 + 本格子的高度 =  本区间的高度

			// 更新本次格子落下来的高度
            max = std::max(max, height);
            res.push_back(max);

			// 将高度写入到树中
            seg.update(L, R, height, 1, N, 1);
        }
        return res;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值