蝴蝶与花 题解
UPD on 2020.11.23
感谢神仙验题人 @QuantAsk 和 @beginend CCCCOrz。
这道题的 idea 最初来源于 P3514 [POI2011]LIZ-Lollipop,那道题利用其它性质可以
然后有一天和 QuantAsk 讨论这题的时候想出了支持修改的
看到有人说这道题卡常 /kk,将数据范围开这么大是因为
有神仙写线段树被卡常,但我和验题人的递归版线段树都是可以在不加 O2 下
std 是树状数组,所以常数小一点,我尝试了很多次,在不加 O2 下都可以在
题意简述
给出一个长度为
算法 1
枚举左端点,发现在左端点不断向右扫描的过程中,右端点的位置也一定单调不减。所以不用每次重新开始扫描右端点,在上一次扫描的基础上继续向右即可。
时间复杂度
算法 2
将原序列做前缀和,设做前缀和后的序列为
对于修改操作,相当于将序列
时间复杂度
甚至没有算法 1 优秀。
算法 3
在算法 2 中,容易发现我们二分出的每一段区间和要么是
假设我们二分出的两个区间为
最后一点换句话说,黄色部分的和一定等于蓝色部分的和,而蓝色部分的和为
那如果再加入一个区间
那么我们用数据结构维护前缀和,对于每一次询问,二分出从位置
-
当
cnt1<cnt2 时,区间[2+cnt1,p+cnt1] 即为答案。 -
当
cnt1\geq cnt2 时,区间[1+cnt2,p+cnt2] 即为答案。
可以手写小数据来理解。
那么我们需要解决两个问题:
-
如何找到第一个前缀和不小于
k 的位置。 -
如何求出一个位置后面有多少个连续的
2 。
对于问题 1,直接采用二分+数据结构即可。对于问题 2,依然可以二分长度,假设为
采用树状数组或者线段树实现均可。
时间复杂度
算法 4
可以在算法 3 的基础上,在数据结构内二分。可以省掉一个
树状数组二分或线段树二分均可,后者写法不优美可能会被卡。
时间复杂度