题目: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;
}
};