梦熊NOIP公开赛 阈值报警色(alarm) 题解
题意简述
我们给定一个长度为\(n\)的颜色序列\(a\),颜色由\([1,m]\)构成,对于任意的颜色\(i\),\(t_i\)为这个颜色的报警阈值。对于\(a\)的一个连续区间,诺颜色\(c\)在其中出现了不少于\(t_c\)次,则触发这个颜色的报警。一个连续区间的报警色为所有出发报警的颜色中的最小值。诺没有颜色触发,则为\(m+1\). 现在对于\(i \in [1,m+1]\)求出报警色为\(i\)的区间数量
\(1 \leq n,m \leq 2 \times 10^5\)
思考
我们考虑枚举区间的右端点,显然,随着左端点的左移,去见的报警色单调不下降。
暴力做法是我们枚举左端点,使用权值线段树维护最小报警值。时间复杂度\(O(n^2log_2n)\) 预计得分\(30pts\)
我们考虑怎么优化计算。
我们依旧固定右端点。
我们考虑对每个颜色和出现的位置排序。
然后我们可以知道对于一个右端点,每个颜色第一次达到报警阈值的位置。
对于右端点\(r\),我们记颜色\(c\)第一次报警的位置为\(f_c(r)\)
我们考虑什么情况下一个颜色会成为去见的报警色。
对于颜色\(c\),但且仅当
的时候这个颜色会产生报警
但是着设计决策,我们如果挨个判断太麻烦了。
然后我们考虑怎么维护每个位置的实际报警颜色。
我们每次右断点的移动,只会影响一个\(f_c(r)\)
由于我们有区间的报警颜色单调不下降。那么我们考虑线段树维护报警的颜色。
那么显然,我们可以通过计算这个右端点的颜色的最近更新位置\(f_{a[r]}(r)\),然后让线段树\(f_{a[r]}(r)\)往左的位置全部对\(a[r]\)取更小值。 然后由于右端点固定的时候左端点的报警颜色单调下降,所以修改的区间是连续的,然后我们就可以使用二分确定修改位置,然后线段树修改了。
但是我们怎么知道每个颜色出现的次数呢?着不是还得照着原来的扫描吗?
那么我们考虑换个角度,既然我们是关于颜色的查询,那么我们就维护关于颜色的线段输。
我们考虑线段数维护每个颜色在固定右端点时的最小左端点。
但是由于我们肯定不能说是每次都对每个颜色进行统计。
那么我们考虑维护每个右端点时的最小左端点的和。
然后我们考虑怎么更新。但是问题在于这个单调性被破坏了。

浙公网安备 33010602011771号