前缀和与差分的应用
前缀和:P10904 [蓝桥杯 2024 省 C] 挖矿
题目描述
小蓝正在数轴上挖矿,数轴上一共有 n n n 个矿洞,第 i i i 个矿洞的坐标为 a i a_i a i 。小蓝从 0 0 0 出发,每次可以向左或向右移动 1 1 1 的距离,当路过一个矿洞时,就会进行挖矿作业,获得 1 1 1 单位矿石,但一个矿洞不能被多次挖掘。小蓝想知道在移动距离不超过 m m m 的前提下,最多能获得多少单位矿石?
输入格式
输入的第一行包含两个正整数 n , m n,m n , m ,用一个空格分隔。
第二行包含 n n n 个整数 a 1 , a 2 , ⋯ , a n a_1, a_2,\cdots, a_n a 1 , a 2 , ⋯ , a n ,相邻整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示答案。
输入输出样例 #1
输入 #1
输出 #1
说明/提示
【样例说明】
路径:0 → − 1 → 0 → 1 → 2 0\to -1\to 0\to 1\to 2 0 → − 1 → 0 → 1 → 2 ,可以对 { 0 , − 1 , 1 , 2 } \{0,-1,1,2\} { 0 , − 1 , 1 , 2 } 四个矿洞挖掘并获得最多 4 4 4 块矿石。
【评测用例规模与约定】
对于 20 % 20\% 20% 的评测用例,1 ≤ n ≤ 10 3 1 \le n \le 10^3 1 ≤ n ≤ 1 0 3 ;
对于所有评测用例,1 ≤ n ≤ 10 5 1 \le n \le 10^5 1 ≤ n ≤ 1 0 5 ,− 10 6 ≤ a i ≤ 10 6 -10^6 \le a_i \le 10^6 − 1 0 6 ≤ a i ≤ 1 0 6 ,1 ≤ m ≤ 2 × 10 6 1 \le m \le 2 \times 10^6 1 ≤ m ≤ 2 × 1 0 6 。
解决方案
在这道题的情景下,我们显然需要先判断哪个方向上的矿石数目多,哪个方向上的矿石数目多就往哪个方向上挖。同时再用一个变量或者数组来记录剩余的步数,每挖一个矿就检查剩余的步数,来确保能得到一个最优解。
而如果要判断哪个方向上剩余的矿石数目多,我们就可以使用前缀和 的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 def main (): n, m = map (int , input ().split()) holes = list (map (int , input ().split())) N = 2000005 ls = [0 ] * N rs = [0 ] * N zeros = 0 for hole in holes: if hole < 0 : ls[-hole] += 1 elif hole == 0 : zeros += 1 else : rs[hole] += 1 for i in range (1 , m+1 ): ls[i] += ls[i-1 ] rs[i] += rs[i-1 ] ans = 0 for i in range (1 , m+1 ): count = ls[i] if m - 2 * i > 0 : count += rs[m-2 *i] ans = max (count, ans) count = rs[i] if m - 2 * i > 0 : count += ls[m-2 *i] ans = max (count, ans) ans += zeros print (ans)if __name__ == "__main__" : main()
Bingo!
差分:P10903 [蓝桥杯 2024 省 C] 商品库存管理
题目描述
在库存管理系统中,跟踪和调节商品库存量是关键任务之一。小蓝经营的仓库中存有多种商品,这些商品根据类别和规格被有序地分类并编号,编号范围从 1 1 1 至 n n n 。初始时,每种商品的库存量均为 0 0 0 。
为了高效地监控和调整库存量,小蓝的管理团队设计了 m m m 个操作,每个操作涉及到一个特定的商品区间,即一段连续的商品编号范围(例如区间 [ L , R ] [L, R] [ L , R ] )。执行这些操作时,区间内每种商品的库存量都将增加 1 1 1 。然而,在某些情况下,管理团队可能会决定不执行某些操作,使得这些操作涉及的商品区间内的库存量不会发生改变,维持原有的状态。
现在,管理团队需要一个评估机制,来确定如果某个操作未被执行,那么最终会有多少种商品的库存量为 0 0 0 。对此,请你为管理团队计算出,对于每个操作,如果不执行该操作而执行其它操作,库存量为 0 0 0 的商品的种类数。
输入格式
输入的第一行包含两个整数 n n n 和 m m m ,分别表示商品的种类数和操作的个数。
接下来的 m m m 行,每行包含两个整数 L L L 和 R R R ,表示一个操作涉及的商品区间。
输出格式
输出 m m m 行,每行一个整数,第 i i i 行的整数表示如果不执行第 i i i 个操作,则最终库存量为 0 0 0 的商品种类数。
输入输出样例 #1
输入 #1
输出 #1
说明/提示
【样例说明】
考虑不执行每个操作时,其余操作对商品库存的综合影响:
不执行操作 1 1 1 :剩余的操作是操作 2 2 2 (影响区间 [ 2 , 4 ] [2, 4] [ 2 , 4 ] )和操作 3 3 3 (影响区间 [ 3 , 5 ] [3, 5] [ 3 , 5 ] )。执行这两个操作后,商品库存序列变为 [ 0 , 1 , 2 , 2 , 1 ] [0, 1, 2, 2, 1] [ 0 , 1 , 2 , 2 , 1 ] 。在这种情况下,只有编号为 1 1 1 的商品的库存量为 0 0 0 。因此,库存量为 0 0 0 的商品种类数为 1 1 1 。
不执行操作 2 2 2 :剩余的操作是操作 1 1 1 (影响区间 [ 1 , 2 ] [1, 2] [ 1 , 2 ] )和操作 3 3 3 (影响区间 [ 3 , 5 ] [3, 5] [ 3 , 5 ] )。执行这两个操作后,商品库存序列变为 [ 1 , 1 , 1 , 1 , 1 ] [1, 1, 1, 1, 1] [ 1 , 1 , 1 , 1 , 1 ] 。在这种情况下,所有商品的库存量都不为 0 0 0 。因此,库存量为 0 0 0 的商品种类数为 0 0 0 。
不执行操作 3 3 3 :剩余的操作是操作 1 1 1 (影响区间 [ 1 , 2 ] [1, 2] [ 1 , 2 ] )和操作 2 2 2 (影响区间 [ 2 , 4 ] [2, 4] [ 2 , 4 ] )。执行这两个操作后,商品库存序列变为 [ 1 , 2 , 1 , 1 , 0 ] [1, 2, 1, 1, 0] [ 1 , 2 , 1 , 1 , 0 ] 。在这种情况下,只有编号为 5 5 5 的商品的库存量为 0 0 0 。因此,库存量为 0 0 0 的商品种类数为 1 1 1 。
【评测用例规模与约定】
对于 20 % 20\% 20% 的评测用例,1 ≤ n , m ≤ 5 × 10 3 1 \le n,m \le 5 \times 10^3 1 ≤ n , m ≤ 5 × 1 0 3 ,1 ≤ L ≤ R ≤ n 1\le L \le R \le n 1 ≤ L ≤ R ≤ n 。
对于所有评测用例,1 ≤ n , m ≤ 3 × 10 5 1 \le n,m \le 3 \times 10^5 1 ≤ n , m ≤ 3 × 1 0 5 ,1 ≤ L ≤ R ≤ n 1 \le L \le R \le n 1 ≤ L ≤ R ≤ n 。
解决方案
这道题涉及了区间的计算,而在需要频繁进行区间更新的场景中,差分 数组可以提供高效的解决方案。
关于差分在区间计算中的特殊性可以由下边这个简单的示例来说明:
不难发现,若对原数组区间[l,r]整体加上一个k,则对于其差分数组b
来说,就是b[l] += 1
,b[r+1] -= 1
。随后再对该差分数组进行前缀和运算即可得到原数组。
那么我们也就得到了对于此题的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def main (): lrs = [] n, m = map (int , input ().split()) for i in range (m): l, r = map (int , input ().split()) lrs.append((l, r)) for i in range (m): lrs_copy = lrs[:i]+lrs[i+1 :] goods = [0 ] * (n + 5 ) for j in range (1 , n+1 ): goods[i] -= goods[i-1 ] for l, r in lrs_copy: goods[l-1 ] += 1 goods[r] -= 1 for j in range (1 , n+1 ): goods[j] += goods[j-1 ] print (goods[:n].count(0 ))if __name__ == "__main__" : main()
需要注意的是,这段代码的时间复杂度较高,但这里我们仅用于掌握差分的思想,不再对其进行优化。