Loading

4.8 CW 模拟赛 T3. 皮卡丘 & [NOI 2010] 超级钢琴

前言

对于模拟赛 \(\rm{T3}\), 我们深刻弄懂暴力, 然后简单看一下正解
对于 \(\textrm{[NOI 2010]}\) 超级钢琴, 只关注小问题

思路

首先, 转化问题

题意

给定数组 pp, 询问 mm 次, 每次询问提取 [L,R][L, R] 区间, 查询 alara_l - a_r 的前 kk 大值之和, 其中 lr,l,r[L,R]l \leq r, l,r \in [L, R]

p,m1000,k3×105|p|, m \leq 1000, \sum k \leq 3 \times 10^5

其中 \(\textrm{[NOI 2010]}\) 超级钢琴 就是单次询问 \([1, n]\), 然后对 \(l, r\) 约束更强的问题

大体上来讲是这样的


考虑一个做法
\(\phi(p, u, v)\) 表示 \(l = p, r \in [u, v]\) 的最大 \(a_l - a_r\)
这个显然不难做, 是一个经典的对 \(a_r\)\(\rm{RMQ}\) 问题

最初先把每个端点 \(i\) 对应的 \(\phi(i, i, n)\) 求出来, 加入堆中
然后每次取出一个 \(\phi(p, u, v)\), 假设 \(\phi(p, u, v)\) 对应的最优解位置为 \(t\), 那么加入 \(\phi(p, u, t - 1)\)\(\phi(p, t + 1, v)\) 即可, 都是现算现加以保证复杂度


发现还有一档 \(k = 1\) 的情况, 要求 \(\mathcal{O} (\log n)\) 处理一次询问

这个怎么做呢?
不难想到, 可以枚举分割线, 然后左右最值去做

有没有招笑高效一点的做法呢?
想到每次修改仅仅只是区间加, 会不会可以区间答案而不用每次都重新统计?
给区间加区间 \(\max\) 线段树加上一个参数 \(ans\) 表示当前区间的答案

考虑线段树解决
对于每个点我们维护: 区间最大值 \(\max\)、区间最小值 \(\min\)、区间的最大答案 \(ans\)
这样对于一个节点 \(p\),

\[ans_p = \max(ans_{p\to ls}, ans_{p\to rs}, \textrm{max}_{p\to ls} - \textrm{min}_{p\to rs}) \]

区间 \(\rm{query}\) 方法类似
也就是把两段合并的时候也用类似的方法

对于区间加, \(tag\)\(\max, \min\) 的影响都是直接加, 而对 \(ans\) 没有影响

考虑其本质, 对于这种动态拆分问题, 我们显然可以线段树上的每个节点就作为动点拆分处维护区间答案, 再合并上左右儿子答案\((\)合并的作用是避免每次取 \(\min\)\()\)

总结

这套题深刻的体现了出题人的思维\(\rm{tm}\) 是这种问题
也就是一种什么思想呢?

\(k\) 大的问题
往往就是这样依赖性的加入

posted @ 2025-04-09 07:50  Yorg  阅读(28)  评论(0)    收藏  举报