厦门大学夏令营机试第四题-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]
。