前缀和
问题引入
package mainimport ("fmt"
)func main() {var n, q, l, r intfmt.Scan(&n, &q)a := make([]int, n)ap := make([]int64, n + 1)ap[0] = 0for 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试试
package mainimport ("bufio""fmt""os""strconv""strings"
)func main() {/*fmt.Scan()不会处理换行符,所以后面用sc.Scan()会读取换行符*//*改用fmt.Scanln()读取一行,且会丢弃换行符*/var n, q, l, r int//var s stringfmt.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] = 0sc := 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运行:
但牛客上运行:
于是,开始对输入输出好好研究:
package mainimport ("bufio""fmt""os"
)func main() {var (n, q, l, r intin = 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] = 0for 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()}
}
那么在此前提下,如果第二行输入不一个个读入,用整行读入呢?
(其实到这,我就有了对自己之前行为的评价:之前代码的各种输入输出用的很混乱,想用哪一套就彻底用哪一套呗,快不快慢不慢的,看着就恶心)
package main// 前缀和很简单,往往输入数据会很变态,所以不能用fmt.Scan()和fmt.Println()
// 有好几种优化的输入输出// 用封装好的bufio.NewReader(os.Stdin)和bufio.NewWriter(os.Stdout)/*
var (n, q, l, r intin = 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] = 0for 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 stringfor _, 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 intsc = 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()
}