leetcode 699.掉落的方块(线段树&离散化)
tag:线段树、离散化。
题意: 给出二维数组positions(代码中改为f),每一项f[i] = [left , lenghth],left表示左边界,length表示从左边届到右边界的距离。方块为正方形(高等同于宽),现按顺序从无穷高掉落方块,方块在下落过程若有遇到方块则会立马停止定住不动(类似俄罗斯方块规则),求每块方块落下后的整个图的最大高度。
数据范围:方块数 <= 1e3 , left <= 1e8 , length <= 1e6。
思路: 将题目转化成求整个范围的最大值,初始全部为0,后面下落方块由于会在其范围最高处停下,即将方块范围内的值全部重置成maxh[l,r] + h(方块范围d的原本最高值+方块高)。由于坐标点跨度过大, 直接用线段树维护数据范围过大,数组无疑会越界,故须对坐标点进行离散化。
注意: 需要注意的是边界处理,如[3,4]与[4,6]不叠加,但在使用线段树时明显会产生叠加,弱化边界为左闭右开[3,4) , [4,6),在实际代码中直接将右边界-1即可,即[3,3] , [4,5]。
代码:
// LH
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
const int N = 2e3 + 3;
//掉落的方块
//线段树、离散化
//范围重置,维护范围最大值
/*
转化为范围重置,查询范围最大值,需要注意边界处理,如[3,4]与[4,6]不叠加,但在使用线段树时明显会产生叠加,弱化边界为左闭右开[3,4) , [4,6)
在实际操作中直接右边界-1即可,即[3,3] , [4,5]。
由于数据原因需要对坐标点进行离散化
*/
class Solution {
public:
int ls(int x) {return x << 1;}
int rs(int x) {return x << 1 | 1;}
ll tree[N<<2] , tag[N<<2];
map<int,int> ff;
int n;
inline void up(int p) {tree[p] = max(tree[ls(p)] , tree[rs(p)]);}
inline void down(int p , int l , int r) {;
if(tag[p]) {
tag[ls(p)] = tag[p];
tag[rs(p)] = tag[p];
tree[ls(p)] = tag[p];
tree[rs(p)] = tag[p];
tag[p] = 0;
}
}
inline void update(int l , int r , int p , int lx , int rx , int x) {
if(lx <= l && r <= rx) {
tree[p] = x;
tag[p] = x;
cout << tree[p] << '\n';
return;
}
down(p , l , r);
int mid = l + r >> 1;
if(lx <= mid) update(l , mid , ls(p) , lx , rx , x);
if(rx > mid) update(mid+1 , r , rs(p) , lx , rx , x);
up(p);
}
inline int query(int l , int r , int p , int lx , int rx) {
if(lx <= l && r <= rx) {
return tree[p];
}
down(p , l , r);
int mid = l + r >> 1;
int res = 0;
if(lx <= mid) res = max(res , query(l , mid , ls(p) , lx , rx));
if(rx > mid) res = max(res , query(mid+1 , r , rs(p) , lx , rx));
return res;
}
vector<int> fallingSquares(vector<vector<int>>& f) {
vector<int> fff;
for(int i = 0;i < f.size();i ++) {
fff.emplace_back(f[i][0]);
f[i][1] += f[i][0] - 1; //将f[i][1]转化成方块右边界坐标-1
fff.emplace_back(f[i][1]);
}
//排序&去重,进行离散化
sort(fff.begin() , fff.end());
fff.resize(unique(fff.begin() , fff.end()) - fff.begin());
for(int i = 0;i < fff.size();i ++) {
ff[fff[i]] = i+1;
}
n = ff[fff.back()];
vector<int> ans;
for(int i = 0;i < f.size();i ++) {
int l = ff[f[i][0]] , r = ff[f[i][1]] , h = f[i][1] - f[i][0] + 1 + query(1 , n , 1 , l , r); //将方块范围内高度重置为范围内最高值+方块高
update(1 , n , 1 , l , r , h);
ans.emplace_back(tree[1]);
}
return ans;
}
};