兔队线段树

Gavin

这是一种使用线段树维护前缀最值的算法。

我们从楼房重建这道题入手。

给定长为 nn 的序列 hh,初始全为 00,支持单点修改。
定义 si=hiis_i = \frac{h_i}{i}
每次查询求满足 hi>0h_i > 0si>max1j<isjs_i > \max_{1 \leq j < i} s_jii 的个数。

查询的条件可以等价理解为 ii 合法意味着 sis_i前缀严格最大值

我们使用线段树维护,对于每个区间,保存如下信息。

  • 区间内的 sis_i 最大值。
  • 不考虑区间外信息的情况下,区间内的答案。

设其分别为 maxsmaxscntcntmaxsmaxs 是好维护的,重点在于 cntcnt 如何维护。设现在要从 uu 的子树转移到 uu,如果用左右子树的信息直接相加显然是错的,因为没有考虑左子树对右子树的影响。左子树的信息是可以直接继承的,右子树利用左子树的信息重新计算即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int calc(int u,int l,int r,ld pre){
if(l==r){
return tr[u].mx>pre;
}
int mid=(l+r)/2;
if(tr[u*2].mx>pre){
return calc(u*2,l,mid,pre)+tr[u].cnt-tr[u*2].cnt;
}
return calc(u*2+1,mid+1,r,pre);
}

void pushUp(int u,int l,int r){
int mid=(l+r)/2;
tr[u].mx = max(tr[u*2].mx,tr[u*2+1].mx);
tr[u].cnt = tr[u*2].cnt+calc(u*2+1,mid+1,r,tr[u*2].mx);
}
  • 标题: 兔队线段树
  • 作者: Gavin
  • 创建于 : 2026-07-20 19:43:00
  • 更新于 : 2026-07-20 19:43:00
  • 链接: https://gavin-blog.pages.dev/2026/兔队线段树/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
目录
兔队线段树