厦门大学夏令营机试第四题-13位ISBN号的校验码计算和输出
在处理大范围坐标的区间求和时,可以使用离散化技术和前缀和结合来提高效率。本文将介绍如何使用C++实现这一方法。
假定有一个无限长的数轴,数轴上每个坐标都是0。
现在,我们首先进行n次操作,每次操作将某一位置x上的数加c。
接下来,进行m次询问,每个询问包含两个整数l和r,你需要求出在区间[l,r]之间所有数的和。
第一行包含两个整数n、m。
接下来n行,每行包括两个整数x和c。
再接下来里m行,每行包括两个整数l和r。
共m行,每行输入一个询问中所求得区间内数字和。
以下是一个实现高级前缀和的完整C++代码示例:
1 |
|
以下是一些示例输入和对应的输出,帮助理解代码的工作原理。
输入:1
2
3
4
5
63 2
1 2
2 3
4 5
1 2
2 4
输出:1
25
8
输入:1
2
3
4
5
6
7
84 3
1 1
2 2
3 3
4 4
1 3
2 4
1 4
输出:1
2
36
9
10
输入:1
2
3
4
52 2
100 1
200 2
100 200
150 250
输出:1
23
2
cin 函数读取操作数 m 和查询数 n。当然可以。下面是一个具体的例子以及按照代码处理流程的解释:
假设输入如下:
1 | 3 2 |
3 2 表示有3个添加操作和2个查询操作。1 5,2 6,3 7 是3个添加操作,表示在坐标1加上5,在坐标2加上6,在坐标3加上7。1 3,2 3 是2个查询操作,分别查询区间 [1, 3] 和 [2, 3] 的和。读取输入并存储操作:
1 | int m, n; |
m = 3,n = 2。
1 | for (int i = 0; i < m; i++) { |
处理添加操作,将坐标 b 存入 alls,并将操作 (b, c) 存入 add。
alls = [1, 2, 3],
add = [(1, 5), (2, 6), (3, 7)]。
1 | for (int i = 0; i < n; i++) { |
处理查询操作,将区间起点和终点 b, c 存入 alls,并将操作 (b, c) 存入 question。
alls = [1, 2, 3, 1, 3, 2, 3],
question = [(1, 3), (2, 3)]。
离散化处理:
1 | sort(alls.begin(), alls.end()); |
对 alls 进行排序和去重。
alls = [1, 2, 3]。
执行添加操作:
1 | for (auto x : add) { |
将添加操作应用到离散化后的数组 a 中。
find(1) = 1,find(2) = 2,find(3) = 3。
更新后 a 数组的变化:
a = [0, 5, 6, 7]。
构建前缀和数组:
1 | for (int i = 1; i <= alls.size(); i++) |
构建前缀和数组 s。
前缀和数组 s:
s = [0, 5, 11, 18]。
处理查询操作并输出结果:
1 | for (auto x : question) { |
处理查询操作并输出结果。
[1, 3]:find(1) = 1,find(3) = 3,s[3] - s[0] = 18 - 0 = 18。[2, 3]:find(2) = 2,find(3) = 3,s[3] - s[1] = 18 - 5 = 13。1 | 18 13 |
通过这个例子,我们可以看到代码是如何处理添加和查询操作的。代码通过离散化技术将原始坐标映射到较小的连续整数范围,从而在固定大小的数组上执行操作,这显著提高了处理效率。
在处理数组区间求和时,可以使用前缀和技术来提高效率。本文将介绍如何使用C++实现前缀和。
以下是一个实现前缀和的完整C++代码示例:
1 |
|
以下是一些示例输入和对应的输出,帮助理解代码的工作原理。
输入:1
2
3
4
55 3
1 2 3 4 5
1 3
2 4
1 5
输出:1
2
36
9
15
输入:1
2
3
46 2
1 1 1 1 1 1
1 6
3 5
输出:1
26
3
输入:1
2
34 1
10 20 30 40
2 3
输出:1
50
scanf 函数读取数组长度 n 和查询次数 m。f 中。f,使 f[i] 表示前 i 个元素的和。f[y] - f[x - 1]。