CF1917C:Watering an Array 题解
C:
转化后题意:给出数列a,以及操作数列b,每次操作把 a 数列 \([1,b_i]\) 的每个树加一,问第几次操作后 \(a_i=i\) 的位置最多。
作为 div2 的 C 题,数据中的 n 只给到了 2000,但其实这题 n 给到 1e6 都能做。
Solution:
原题中的 b 数列可以很长,但根据题意发现只需要截取前 2n 的长度就行,因为如果你不能在 2n 步之内将所有 \(a_i\) 变成 i,我们就可以从一开始就采用 “12121212” 操作产生 n 次贡献。
将每个 \(a_i\) 减去 i,我们想知道哪个时间 \(a_i=0\) 的数量最多,然后发现 \(a_i=0\) 是一个时间段,每个操作看做线段覆盖的话,\(a_i=0\) 就是从 \(-a_i\) 条覆盖到 i 的线段到 \(-a_i+1\) 条覆盖到 i 的线段之间。
所以我们把脑袋转90度,把操作的序号看做一个个位置,从左到右扫描 a 数列,出现某操作线段的左端点时,在树状数组中操作的序号处加一,出现右端点就减去一,对于每个数二分 “出现 k 条线段的位置”。二分加树状数组是俩log,直接树状数组二分,一个log,常数还小。
然后就是a数列每个数字求出了对答案产生贡献的区间,可以差分记录区间加一,O(n)找出答案最大的时刻。