树状数组维护区间最值
参考:(LbyG: 树状数组求区间最大值)https://blog.csdn.net/u010598215/article/details/48206959
支持两种操作:
- 修改一个位置的数;
- 求区间最值;
当然不能像普通的树状数组维护区间和一样做
单点修改
先来看一份代码:
while(x <= n) {
t[x] = max(t[x], a[u])
x += lowbit(x);
}
这个代码当然是不对的, 为什么呢?
将一个可能是区间最大值的数换成一个更小的数, 但是最大值并没有变小.
因为树状数组每个位置所维护的区间是\((x - lowbit_x, x)\)
因此需要将包含这个位置的区间全部置0然后更新一遍.
当然这个过程画画图才能明白, 毕竟树状数组就是一个比较抽象的东西.
一种比较快的维护这个过程的方式是:
用这个位置更新每个区间时, 顺便用这个区间所包含的小区间去更新它, 这样就算小区间也包含了这个位置, 而小区间一定被提前更新过.
void updata(int x, int k) {
while (x <= n) {
h[x] = k;
int low = lowbit(x);
for (int i = 1; i < low; i <<= 1)
h[x] = max(h[x], h[x - i]);
x += lowbit(x);
}
}
区间查询
当然也不能直接用区间和的方式来查询.
因为一般区间和的写法是用前缀和的形式\(A_r - A_{l - 1}\)
而显然区间最值是不满足可减性的.
因此只要利用树状数组每个位置所维护的区间是\((x - lowbit_x, x)\)这条性质即可.
int query(int x, int y) {
int ans = 0;
while (y >= x)
{
ans = max(a[y], ans), y -= 1;
for (; y-lowbit(y) >= x; y -= lowbit(y))
ans = max(h[y], ans);
}
return ans;
}