通过前缀和来看golang的acm输入输出

前缀和

问题引入

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()
}
相关推荐
ywf12151 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
程序员爱钓鱼1 小时前
Go排序核心库: sort包深度指南
后端·面试·go
dapeng28701 小时前
分布式系统容错设计
开发语言·c++·算法
qq_417695051 小时前
代码热修复技术
开发语言·c++·算法
badhope6 小时前
Mobile-Skills:移动端技能可视化的创新实践
开发语言·人工智能·git·智能手机·github
码云数智-园园7 小时前
微服务架构下的分布式事务:在一致性与可用性之间寻找平衡
开发语言
C++ 老炮儿的技术栈7 小时前
volatile使用场景
linux·服务器·c语言·开发语言·c++
hz_zhangrl7 小时前
CCF-GESP 等级考试 2026年3月认证C++一级真题解析
开发语言·c++·gesp·gesp2026年3月·gespc++一级
大阿明7 小时前
Spring Boot(快速上手)
java·spring boot·后端
Liu628888 小时前
C++中的工厂模式高级应用
开发语言·c++·算法