CF543E Listening to Music 题解

Codeforces
Luogu
Solution of x义x

Description.

有个序列长度为 \(n\)\(f(l,x)=\sum_{i=l}^{l+m-1}[a_i<x]\)
多次询问,每次询问 \(\min_{i=l}^rf(i,x)\),强制在线。

Solution.

考虑可以离线怎么做。
首先按照 \(a_i\) 升序排列。
从小到大枚举 \(a_i\),如果 \(a_i< x\),那就相当于 \(f(k,x),k\in[i-m+1,i])\) 区间加一。
然后直接线段树随便维护一下就行了,复杂度 \(O(n\log n)\)

考虑现在强制在线了。
我会可持久化线段树!
一看空间,显然直接被卡了。

首先注意到所有的修改都是已知的。
可以考虑对修改进行分块,每 \(\sqrt n\) 个修改记录一下当前的状态。
然后我们就只剩下 \(\sqrt n\) 个修改无法处理,发现每个修改只能 \(O(1)\)
考虑对序列也分块,这样每次修改被拆成了若干个整块和若干个散块。
整块可以直接差分打 tag 最后统计。
散块很难处理,但是考虑到散块总共只有 \(O(n)\) 个。
可以暴力维护出到操作 \(r\) 所有被散块影响区间的最大值。
相当于我们可以处理到 \(r\) 只做散块的块内最大值、前缀最大值、后缀最大值。
然后加一下整块的 tag 就行了。
总复杂度 \(O(n\sqrt n)\),空间复杂度 \(O(n\sqrt n)\) 炸了。

询问散块是可以直接从左往右扫。
每个位置在差分数组上是否为 \(1\) 是可以 \(O(1)\) 计算。
那就需要处理询问整块的情况,相当于有 \(\sqrt n\) 个块,\(\sqrt n\) 个修改。
修改整块可以直接把 tag 打到整块上差分,然后最后 push 一遍,可以一只根号。
修改散块考虑总共只有 \(O(n)\) 种,可以预处理一个前缀修改完后当前这个区间最大值应该是多少。
就如果你一个位置当前没被修改,可以直接找到上一个被修改的位置,查询之前的答案。
这样总信息是 \(O(n)\) 的,预处理复杂度也是 \(O(n\sqrt n)\) 的。

然后就做完啦!!写个 dam。

posted @ 2021-11-16 19:41  Peal_Frog  阅读(49)  评论(0编辑  收藏  举报