(nice!!!)LeetCode 699. 掉落的方块(线段树、暴力枚举)

题目:699. 掉落的方块

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法一:暴力枚举,时间复杂度0(n^2)。第一层for循环遍历每个方块i,第二层for循环遍历已经落下的方块j(j<i)。如果第一层for循环的方块i会落在第二层for循环方块j的上面,那么就比较当前的高度。细节看注释

class Solution {
public:
    vector<int> fallingSquares(vector<vector<int>>& positions) {
        int n=positions.size();
        //保存当前方块i的高度
        vector<int> v(n);
        v[0]=positions[0][1];
        //保存当前方块落下后,方块堆叠的最高高度
        vector<int> mx(n);
        mx[0]=v[0];
        //第一层for循环遍历每个方块i
        for(int i=1;i<n;i++){
            v[i]=positions[i][1];
            int l1=positions[i][0],r1=l1+positions[i][1];
            //第二层for循环遍历已经落下的方块j(j<i)
            for(int j=0;j<i;j++){
                int l2=positions[j][0],r2=l2+positions[j][1];
                //方块i落在方块j的上面
                if(l1<r2&&r1>l2){
                    v[i]=max(v[i],v[j]+positions[i][1]);
                }
            }
            mx[i]=max(mx[i-1],v[i]);
        }
        return mx;
    }
};

方法二:线段树,时间复杂度0(nlogn)。因为范围在1~10^8,所以这里用到离散化。将所有可能的坐标点进行离散化,再进行线段树操作。细节看注释
(线段树:区间修改,区间查询)洛谷P3372 【模板】线段树 1

class Solution {
public:
    //lazy是懒惰标记
    int f[2010<<2],lazy[2010<<2];
    void pushUp(int u){
        f[u]=max(f[u<<1],f[u<<1|1]);
    }
    void pushDown(int u){
        f[u<<1]=lazy[u];
        f[u<<1|1]=lazy[u];
        lazy[u<<1]=lazy[u];
        lazy[u<<1|1]=lazy[u];
        lazy[u]=0;
    }
    int query(int u,int l,int r,int L,int R){
        //cout<<l<<":"<<r<<endl;
        if(L<=l&&r<=R){
            //cout<<f[u]<<endl;
            return f[u];
        }
        
        if(r<L||l>R) return 0;
        int mid=(l+r)/2;
        if(lazy[u]!=0) pushDown(u);
        return max(query(u<<1,l,mid,L,R),query(u<<1|1,mid+1,r,L,R));
    }
    void add(int u,int l,int r,int L,int R,int h){
        if(L<=l&&r<=R){
            f[u]=h;
            lazy[u]=h;
            return ;
        }
        if(r<L||l>R) return;
        int mid=(l+r)/2;
        if(lazy[u]!=0) pushDown(u);
        if(L<=mid) add(u<<1,l,mid,L,R,h);
        if(R>mid) add(u<<1|1,mid+1,r,L,R,h);
        pushUp(u);
    }

    vector<int> fallingSquares(vector<vector<int>>& positions) {
    	//将所有可能的坐标点进行离散化
        set<int> st;
        for(auto tmp:positions){
            st.insert(tmp[0]);
            st.insert(tmp[0]+tmp[1]-1);
        }
        unordered_map<int,int> mp;
        int idx=0;
        for(auto tmp:st){
            mp[tmp]=++idx;
            cout<<tmp<<":"<<idx<<endl;
        }
        //记录当前方块落下后的高度
        vector<int> v(positions.size());
        memset(f,0,sizeof f);
        memset(lazy,0,sizeof lazy);
        for(int i=0;i<positions.size();i++){
        	//当前方块i的左右边界
            int l=positions[i][0],r=positions[i][0]+positions[i][1]-1;
            //找到离散化后的下标
            l=mp[l],r=mp[r];
            //cout<<l<<":"<<r<<endl;
            //在方块i落下之前,区间[l,r]之间的最大高度
            int tmp=query(1,1,st.size(),l,r);
            //更新方块i的高度
            v[i]=tmp+positions[i][1];
            //cout<<v[i]<<endl;
            //将方块i的区间更新高度
            add(1,1,st.size(),l,r,v[i]);
        }
        for(int i=1;i<v.size();i++){
            v[i]=max(v[i],v[i-1]);
        }
        return v;
    }
};
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值