小美的数组询问
题目
小美拿到了一个由正整数组成的数组,但其中有一些元素是未知的(用 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 计算结果,避免了重复计算。