算法线段树的应用-力扣3479.-将水果装入篮子-III
目录
【算法】线段树的应用-力扣3479. 将水果装入篮子 III
这个题就是线段树的应用,但是与之前的文章相比,此处构建的线段树相当于“最大树”,每个节点存储的不是子节点的和,而是子节点中的最大值。
#include <bit>
class SegmentTree {
vector<int> mx;
void maintain(int o) {
// 根据不同的线段树的需求修改对应的代码,
// 本题需要找到最左边最大的点,因此需要构建最大线段树
mx[o] = max(mx[o * 2], mx[o * 2 + 1]);
}
void build(const vector<int>& a, int o, int l, int r) {
if(l == r) {
mx[o] = a[l];
return;
}
int m = (l + r) / 2;
build(a, o * 2, l, m);
build(a, o * 2 + 1, m + 1, r);
maintain(o);
}
public:
SegmentTree(const vector<int>& a) {
size_t n = a.size();
mx.resize(2 << bit_width(n - 1));
build(a, 1, 0, n - 1);
}
int findFirstAndUpdate(int o, int l, int r, int x) {
if(mx[o] < x) {
return -1;
}
if(l == r) {
mx[o] = -1;
return l;
}
int m = (l + r) / 2;
int i = findFirstAndUpdate(o * 2, l, m, x);
if(i < 0) {
i = findFirstAndUpdate(o * 2 + 1, m + 1, r, x);
}
// 注意更新线段树上部的信息
maintain(o);
return i;
}
};
class Solution {
public:
int numOfUnplacedFruits(vector<int>& fruits, vector<int>& baskets) {
SegmentTree t(baskets);
int n = baskets.size(), result = 0;
for(auto x : fruits) {
if(t.findFirstAndUpdate(1, 0, n - 1, x) < 0) {
result++;
}
}
return result;
}
};
注意此处就涉及到之前说的那个s + t 会溢出的问题,因此不能用移位操作来实现。