专栏文章

区间笛卡尔树

算法·理论参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min99qd3
此快照首次捕获于
2025/12/01 22:39
3 个月前
此快照最后确认于
2025/12/01 22:39
3 个月前
查看原文
考虑这样一类问题:有一个序列 a1na_{1\dots n},每次询问一个区间建出来的笛卡尔树上的一些事情。
不妨假设 aia_i 互不相同,我们需要的是大根笛卡尔树。考虑怎么刻画一个区间 [l,r][l,r] 的笛卡尔树:
  • 首先根是区间最大值:p0=argmaxi[l,r]aip_0=\arg\max\limits_{i\in[l,r]}a_i
  • 考虑根的左子树 [l,p0)[l,p_0),有左子树的根 p1=argmaxi[l,p0)aip_1=\arg\max\limits_{i\in[l,p_0)}a_i
  • 我们可以发现 p1p_1 的右子树就是 p1p_1 在整个序列的笛卡尔树上的右子树;p1p_1 的左子树 p2=argmaxi[l,p1)aip_2=\arg\max\limits_{i\in[l,p_1)}a_i,以此类推直到 pk=lp_k=l
  • 容易发现 pk,pk1,,p0p_k,p_{k-1},\dots,p_0 就是这个区间的所有前缀最大值的位置;根的左儿子就是这些前缀最大值(不包括 p0p_0)和它们在整个序列的笛卡尔树上的右儿子拼起来的结果。
  • 维护的方式因题而异,一种常见的做法是从右到左扫描线,用一个递减的单调栈维护 [l,n][l,n] 的前缀最大值;p1,,pkp_1,\dots,p_k 就是单调栈的一个后缀,在单调栈上维护需要维护的信息。根的右儿子就是全部反过来,在最后拼出来根的信息。
QOJ14417. Roman Numerals
题意:有序列 ai,bia_i,b_i,对区间 aia_i 建出笛卡尔树,点 uufu=buflsu+frsuf_u=b_u-f_{ls_u}+f_{rs_u},求根的答案。
首先我们对整个序列建出笛卡尔树并处理出 fuf_u。先考虑右儿子怎么做,可以发现就是单调栈上的一个后缀 buflsub_u-f_{ls_u} 加起来,做一个前缀和就行。
左儿子也是类似,但是每个点的贡献要乘上 (1)depu(-1)^{dep_u}。我们先将在单调栈上的位置的奇偶性当作深度的奇偶性,询问的时候分讨一下 p0p_0 位置的奇偶性。
通常为了方便,第一步的区间 RMQ 可以直接在单调栈上二分。本题使用线性 RMQ 即可做到线性,但通常没有什么必要。
P5044 [IOI 2018] 会议
题意:有序列 aia_i,每次询问 mini[l,r]j[l,r]maxk[min(i,j),max(i,j)]ak\min\limits_{i\in[l,r]}\sum\limits_{j\in[l,r]}\max\limits_{k\in[\min(i,j),\max(i,j)]}a_k
我们先在笛卡尔树上写出 DP:fu=min(flsu+au(szrsu+1),frsu+au(szlsu+1))f_u=\min(f_{ls_u}+a_u(sz_{rs_u}+1),f_{rs_u}+a_u(sz_{ls_u}+1))
两边是对称的,我们就只考虑左边。我们考虑最小的 ii 使得 pip_i 采用了第二种转移,即 fpi=frs+api(pil+1)f_{p_i}=f_{rs}+a_{p_i}(p_i-l+1),那 fp1=fpi+1j<iapj(szrspj+1)f_{p_1}=f_{p_i}+\sum\limits_{1\le j<i}a_{p_j}(sz_{rs_{p_j}}+1),答案就是所有 pip_i 的结果的最小值。在单调栈上前缀和然后拆贡献,KTT 维护一次函数最值。O(nlog2n)\mathcal O(n\log^2n)
P13540 [IOI 2025] 羊驼的坎坷之旅
题意:有一个网格,一个单元格 (x,y)(x,y) 合法当且仅当 ax>bya_x>b_y,问保留第 [l,r][l,r] 列,(0,x)(0,x) 能不能走到 (0,y)(0,y)
我们猜测路径一定形如一堆 (0,a)(x,a)(x,b)(0,b)(0,a)\to(x,a)\to(x,b)\to(0,b)。设一列中第一个空的位置是 fiifi_i,前缀连续空的长度是 cnicn_iaba\to b 之间的 maxb\max b 位置为 cc,那能这么走就相当于 ficmin(cna,cnb)fi_c\le\min(cn_a,cn_b)
我们建出 bb 的笛卡尔树。对于一个子树 xx,如果我们能到达 fixfi_x 且子树 maxcnfifax\max cn\ge fi_{fa_x} 就可以走到 fifaxfi_{fa_x},询问的时候只要看能跳到最高的位置是否相等。
考虑区间笛卡尔树,所有前缀 max\max 相当于不停跳到右侧第一个 >bi>b_i 的位置,这个也能建出一棵树,在全局的笛卡尔树上倍增到子树不被 [l+1,r1][l+1,r-1] 包含后变成在这棵树上倍增即可。O(nlogn)O(n\log n)

评论

0 条评论,欢迎与作者交流。

正在加载评论...