edu164E(数论分块+思维)
edu164E
先考虑 \(O(n*max(a_{i}))\) 暴力做法:对于每个 \(k\in[1,max(a_{i})]\),第 \(i\) 个怪物需要恰好 \(\lceil \frac{a_{i}}{k} \rceil\) 次攻击。不难想到将 \(a\) 数组转化为 \([\lceil \frac{a_{1}}{k} \rceil], \lceil \frac{a_{2}}{k} \rceil, ..., \lceil \frac{a_{n}}{k} \rceil]\),则问题转化为:每次操作可选取任意区间 \([l, r]\),必须保证区间内的数均大于0,然后将 \([l, r]\) 内的数减1,求将序列内所有数减为0的最小操作次数。
赛时一直在想 \(ds\) 做法,死活想不出来。后来看了题解,发现结论如此之简单:答案就是 \(\sum_{i=1}^{n}max(0, a_{i} - a_{i-1})\)。
证明:对于 \(\forall i\in[2,n]\),只要 \(a_{i-1}\) 还未减到0,则在考虑减小 \(a_{i-1}\) 时,一定可以顺带着将 \(a_{i}\) 减小;当 \(a_{i-1}\) 被减为0时,才考虑单独减小 \(a_{i}\)。因此对于 \(\forall a_{i}\):
- \(a_{i-1}<=a_{i}\) 时,将 \(a_{i}\) 减为0真正需要被计入贡献为 \(a_{i} - a_{i-1}\)
- \(a_{i-1}>a_{i}\) 时,在减小 \(a_{i-1}\) 的过程中 \(a_{i}\) 已先一步减为 \(0\),因此不需要额外对 \(a_{i}\) 操作,相当于真正有用的操作数为0。
现在考虑优化:根据数论分块知识,\(\lceil \frac{a_{i}}{k} \rceil\) 最多只有 \(2\sqrt a_{i}\) 种取值。因此可以在枚举 \(k\) 的过程中,动态地修改相应变化的 \(\lceil \frac{a_{i}}{k} \rceil\) ,总修改次数不超过 \(n *2\sqrt a_{i}\) 次,在修改过程中动态维护 \(\sum_{i=1}^{n}max(0, a_{i} - a_{i-1})\) 即可。具体细节见代码。