P1198 [JSOI2008] 最大数
luogu-p1198-最大数">Luogu-P1198 最大数
1. 题面梗概
-
中译中: 维护一个初始为空的序列,支持两种操作:
-
入队:在序列末尾追加一个数 (实际上是 )。
-
查询:查询序列中最后 个数里的最大值。
-
-
强制在线: 每次追加的数依赖于上一次查询的结果 。
2. 逻辑推导
末尾追加 和 查询最后 个数,第一反应这题可能是个 单调队列 或者 单调栈。
但问题是 是变化的,单调栈无法回答任意长度后缀的最值。
回归本质分析,这其实是个序列问题,末尾追加 类比于 单点修改,以及区间查询。
对于这题来说,可以用普通线段树来维护,第 个叶子节点,就是第 次插入的那个数。这样就是简单的线段树裸题了。
2.1 动态 ST 表
但这题可以采用另类的ST表解决。传统的 ST 表面对动态数据会很乏力,是因为它的区间是从左向右定义的。(st[i][j] 覆盖 [i, i+2^j-1])
逆向思维:既然只在末尾追加元素,且查询总是关于最后 个元素,不妨反转 ST 表定义:st[i][j] 表示以 结尾,长度为 的区间最大值。(覆盖 [i-2^j+1, i])
状态转移:st[i][j] = max( st[i][j-1], st[i - (1 << (j - 1) )][j-1];
这一步很奇妙,巧在前面的元素是固定的,每次追加只需要更新最后面的元素,已经它们对应的 ST 表即可。
2. 代码实现
▶
AcCode
1 | |
4. 复盘
P1198 [JSOI2008] 最大数
http://miqiu.space/posts/3cab7524/