洛谷 P6578

洛谷 P6578

将小于等于 \(x\) 的看作 \(1\),大于 \(x\) 的看作 \(0\),相当于如果有一个长度为 \(k\) 的极长 \(1\) 子串,有 \(k(k + 1)/2\) 的贡献。

先考虑没有修改的情况,把修改按 \(x\) 从小到达排序,直接用线段树维护答案即可。

有了修改不太好做了,考虑分块。对于每个整块,实际只有 \(O(B)\)\(01\) 序列。对于每个块只关心当只有这个块时的贡献和左右两端的极长 "1" 段的长度,维护这些信息,拼上散块是很好合并的。

如何维护呢?其实三个信息只有第一个比较困难,我们从全 \(0\) 开始,一个一个把数变成 \(1\),相当于合并相邻两段,对于每一段在开头标记结尾的位置,结尾标记开头的位置即可 \(O(1)\) 合并。

修改直接暴力重构整个块即可。

查询时,需要找到 \(x\) 在每个块中对应哪种 \(01\) 序列,需要二分一下。

所以总时间复杂度为 \(O(nB + \frac{n^2}{B} \log B)\),总时间复杂度是带了半个 \(\log\), 可以通过根号重构去掉 ,但可能更慢。

因为要考虑常数,块长和理论最佳有差距,实测取 \(B = 600 \sim 700\) 比较合适。

似乎是第一个几乎独立想出来的黑题。

posted @ 2026-02-05 22:38  xiehanrui0817  阅读(3)  评论(0)    收藏  举报