题目描述
给定两个非负数组x和hp,长度都是N,再给定一个正数rangex有序
- x[i]表示i号怪兽在x轴上的位置;
- hp[i]表示i号怪兽的血量
- range表示法师如果站在x位置,用AOE技能打到的范围是:[x-range,x+range],被打到的每只怪兽损失每次1点血量
返回要把所有怪兽血量清空,至少需要释放多少次AOE技能?
题目解析
贪心
我们先假设hp是紧贴在站在一起的(也就是先不看X),假设其hp如下:
因为最终要把所有的怪兽都杀死。
- 我们先看第一个怪兽,其hp为5。那么不管这个怪兽是怎么死的,其一定要被AOE覆盖它5次。
- 我们每次AOE以它为起点,放五次,那么hp数组变为:
-
然后我们再找下一个大于0的怪兽,以它作为AOE的起点,以最少的次数去杀死它,得到如下:
-
然后我们再找下一个大于0的怪兽,以它作为AOE的起点,以最少的次数去杀死它,得到如下:
- 下一个没有大于0的怪兽了,完毕。最终得到
贪心方法无需证明,那怎么验证它的正确性呢?写一个暴力全排列的方法,通过实现对比它们的答案是不是相同,以得到。
如果我们要把x[i]和hp[i]总和起来看呢?x[i]只会影响AOE能够扫描到的怪兽范围,但是贪心策略是不变的。问题: 每次以i怪兽为起点,那么哪些位置能够被波及到呢?
- i位置的怪兽的位置是 x [ i ] x[i] x[i],加上AOE的范围是 x [ i ] + L x[i] + L x[i]+L,那么本次AOE怪兽范围是 x [ i ] . . . . . . . x [ i ] + L − 1 x[i].......x[i] + L - 1 x[i].......x[i]+L−1
- 因为 x [ i ] x[i] x[i]是从小到大的,我们只需要在x[i]数组上从x[i]位置开始,遍历(因为每一个怪都要掉血,所以直接扫描,不二分)到第一个等于 x [ i ] + L − 1 x[i] + L - 1 x[i]+L−1停止(怪兽是不会堆在一起站的,一个位置只能站一个怪兽,所以下一个位置一定大于 x [ i ] + L − 1 x[i] + L - 1 x[i]+L−1,所以我们遍历到 x [ i ] + L − 1 x[i] + L - 1 x[i]+L−1就停止)
- i位置的怪兽的位置是AOE次,每次掉1滴血,所以每次区间内的数都要减少AOE滴血
在上面贪心方法中,我们针对每一个区间范围内的数要做:
- 在全部区间中查询第一个大于0的数(区间查询)
- 在指定区间内将所有数都减少n(区间修改)
所以,可以用线段树来优化上面过程。问题是怎么在全部区间中查询第一个大于0的数(区间查询):
- 先在一个范围上所有数字都减少n,剪完之后在线段树中查:
- i+1 ~ i + 1范围内是不是 大于0的
- i+2 ~ i + 2范围内是不是 大于0的
- i+3 ~ i + 3范围内是不是 大于0的
- …
- 如果找到了第一个大于0的,那么就以这个为起点去AOE