前缀和
问题引入
go
package main
import (
"fmt"
)
func main() {
var n, q, l, r int
fmt.Scan(&n, &q)
a := make([]int, n)
ap := make([]int64, n + 1)
ap[0] = 0
for i := 0; i < n; i++ {
fmt.Scan(&a[i])
ap[i + 1] = ap[i] + int64(a[i])
}
for j := 0; j < q; j++ {
fmt.Scan(&l, &r)
fmt.Println(ap[r] - ap[l-1])
}
}
考虑是不是输入太慢了,用Scanner试试
go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
/*fmt.Scan()不会处理换行符,所以后面用sc.Scan()会读取换行符*/
/*改用fmt.Scanln()读取一行,且会丢弃换行符*/
var n, q, l, r int
//var s string
fmt.Scan(&n, &q)
//fmt.Scanln(s)
//values := strings.Split(s, " ")
//n, _ = strconv.Atoi(values[0])
//q, _ = strconv.Atoi(values[1])
ap := make([]int64, n+1)
ap[0] = 0
sc := bufio.NewScanner(os.Stdin)
sc.Scan()
sc.Scan()
strs := strings.Split(sc.Text(), " ")
for i := range strs {
val, _ := strconv.Atoi(strs[i])
ap[i+1] = ap[i] + int64(val)
}
for i := 0; i < q; i++ {
fmt.Scan(&l, &r)
fmt.Println(ap[r] - ap[l-1])
}
}
// package main
// import (
// "fmt"
// )
// func main() {
// var n, q, l, r int
// fmt.Scan(&n, &q)
// a := make([]int, n)
// ap := make([]int64, n + 1)
// ap[0] = 0
// for i := 0; i < n; i++ {
// fmt.Scan(&a[i])
// ap[i + 1] = ap[i] + int64(a[i])
// }
// for j := 0; j < q; j++ {
// fmt.Scan(&l, &r)
// fmt.Println(ap[r] - ap[l-1])
// }
// }
本地goland运行:
但牛客上运行:
于是,开始对输入输出好好研究:
go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
var (
n, q, l, r int
in = bufio.NewReader(os.Stdin)
out = bufio.NewWriter(os.Stdout)
)
fmt.Fscan(in, &n, &q)
a := make([]int, n)
ap := make([]int64, n+1)
ap[0] = 0
for i := 0; i < n; i++ {
fmt.Fscan(in, &a[i])
ap[i+1] = ap[i] + int64(a[i])
}
for j := 0; j < q; j++ {
fmt.Fscan(in, &l, &r)
fmt.Fprintln(out, ap[r] - ap[l - 1])
// fmt.Println(ap[r] - ap[l-1])
out.Flush()
}
}
那么在此前提下,如果第二行输入不一个个读入,用整行读入呢?
(其实到这,我就有了对自己之前行为的评价:之前代码的各种输入输出用的很混乱,想用哪一套就彻底用哪一套呗,快不快慢不慢的,看着就恶心)
go
package main
// 前缀和很简单,往往输入数据会很变态,所以不能用fmt.Scan()和fmt.Println()
// 有好几种优化的输入输出
// 用封装好的bufio.NewReader(os.Stdin)和bufio.NewWriter(os.Stdout)
/*
var (
n, q, l, r int
in = bufio.NewReader(os.Stdin)
out = bufio.NewWriter(os.Stdout)
)
func main() {
fmt.Fscan(in, &n, &q)
a := make([]int, n)
ap := make([]int64, n+1)
ap[0] = 0
for i := 0; i < n; i++ {
fmt.Fscan(in, &a[i])
ap[i+1] = ap[i] + int64(a[i])
}
for j := 0; j < q; j++ {
fmt.Fscan(in, &l, &r)
fmt.Fprintln(out, ap[r]-ap[l-1])
out.Flush()
}
}
*/
// 用适合于整行读取的组合方法
/*
sc := bufio.NewScanner(os.Stdin)
bs := make([]byte, 20000 * 1024) //设置缓冲区的最大读取
readLine = func() (res string) {
sc.Scan() //读一行
l := strings.Split(sc.Text(), " ")
var res string
for _, s := range l {
res += s
}
return
}
out = bufio.NewWriter(os.Stdout)
scanner.Buffer(bs, len(bs)) //设置缓冲区的最大读取
cur := readLine()
fmt.Fprint(out, cur)
out.Flush()
*/
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
var (
n, p, l, r int
sc = bufio.NewScanner(os.Stdin) //按行扫描器
out = bufio.NewWriter(os.Stdout) //文件输出流(要用fmt.Fprint(out, ...))
bs = make([]byte, 20000*1024) //设置缓冲区最大读取
readLine = func() (res []int) { //把读取一行的操作封装成一个匿名函数
sc.Scan() //扫描器读取一行
strs := strings.Split(sc.Text(), " ") //将读取的字符串分割成切片
res = make([]int, len(strs)) //这一句不能遗漏,返回值是切片类型,必须要有初始化
for i, s := range strs { //将切片中的每个元素转换为int类型,再存入返回值切片里
x, _ := strconv.Atoi(s)
res[i] = x
}
return
}
)
func main() {
sc.Buffer(bs, len(bs)) //设置缓冲区读取最大数量
cur1 := readLine() //读第一行
ap := make([]int64, cur1[0]+1) //前缀和数组(切片)
cur2 := readLine() //读第二行
for i := range cur2 {
ap[i+1] = ap[i] + int64(cur2[i]) //求前缀和
}
for i := 0; i < cur1[1]-1; i++ { //求要求的区间内的数值和
cur := readLine()
fmt.Fprintln(out, ap[cur[1]]-ap[cur[0]-1])
}
//最后一组单独写是为了防止最后多个换行
cur := readLine()
fmt.Fprint(out, ap[cur[1]]-ap[cur[0]-1])
//最后一下给Flush出来
out.Flush()
}