小美的数组询问
题目
小美拿到了一个由正整数组成的数组,但其中有一些元素是未知的(用 0 来表示)。现在小美想知道,如果那些未知的元素在区间[l,r][l,r]范围内随机取值的话,数组所有元素之和的最小值和最大值分别是多少?共有qq次询问。
构思
直接记录非零元素之和,然后记录0元素的数目,最小值即为sum+0元素数目*取值最小值,最大值即为sum+0元素数目*取值最大值
代码实现
首次实现
使用scan进行输入
func main() {
var n, q int
fmt.Scan(&n, &q)
nums := make([]int, n)
number0 := 0
sum := 0
for i := 0; i < n; i++ {
fmt.Scan(&nums[i])
if nums[i] == 0 {
number0++
}
sum += nums[i]
}
for i := 0; i < q; i++ {
var l, r int
fmt.Scan(&l, &r)
fmt.Println(sum + number0 * l, sum + number0 * r)
}
}
代码优化
我们发现代码的绝大部份时间都花在了读取数据上面,所以我们通过buffer来进行优化读取,减少数据读取时间
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
// 读取 n 和 q
line, _ := reader.ReadString('\n')
fields := strings.Fields(line)
n, _ := strconv.Atoi(fields[0])
q, _ := strconv.Atoi(fields[1])
// 读取数组 nums
nums := make([]int, n)
line, _ = reader.ReadString('\n')
fields = strings.Fields(line)
number0 := 0
sum := 0
for i := 0; i < n; i++ {
nums[i], _ = strconv.Atoi(fields[i])
if nums[i] == 0 {
number0++
}
sum += nums[i]
}
// 处理查询
for i := 0; i < q; i++ {
line, _ := reader.ReadString('\n')
fields := strings.Fields(line)
l, _ := strconv.Atoi(fields[0])
r, _ := strconv.Atoi(fields[1])
// 计算结果
result1 := sum + number0*l
result2 := sum + number0*r
// 输出结果
fmt.Fprintln(writer, result1, result2)
}
}
优化点
(1) 使用 bufio 加速输入输出
- 使用 bufio.NewReader 和 bufio.NewWriter 来加速输入输出。
- reader.ReadString('\n') 读取一行输入。
- strings.Fields 将输入行拆分为字段。
- strconv.Atoi 将字符串转换为整数。
(2) 减少重复计算
- 在查询处理部分,直接使用 sum 和 number0 计算结果,避免了重复计算。
查看9道真题和解析