前缀和|AcWing 795. 前缀和|AcWing 796. 子矩阵的和

前缀和

AcWing 795. 前缀和

package main

import "fmt"

func main() {
	var n, m int
	fmt.Scan(&n, &m)
	nums := make([]int, n+1)
	preSum := make([]int, n+1)
	for i := 1; i <= n; i++ {
		fmt.Scan(&nums[i])
		preSum[i] = preSum[i-1] + nums[i]    // 重要
	}
	var l, r int
	for ; m > 0; m-- {
		fmt.Scan(&l, &r)
		fmt.Println(preSum[r] - preSum[l-1])
	}
}

二维数组前缀和基础案例

package main

import "fmt"

func main() {
	a := [][]int{
		{0, 0, 0, 0},
		{0, 1, 2, 3},
		{0, 4, 5, 6},
		{0, 7, 8, 9},
	}
	s := [][]int{
		{0, 0, 0, 0},
		{0, 0, 0, 0},
		{0, 0, 0, 0},
		{0, 0, 0, 0},
	}
	for i := 1; i <= 3; i++ {
		for j := 1; j <= 3; j++ {
			s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j] // 求前缀和
		}
	}
	fmt.Println(s[3][3])

	// 求子数组之和
	// [5,6]
	// [8.9]
	subMatrix := s[3][3] - s[1][3] - s[3][1] + s[1][1]
	fmt.Println(subMatrix)
}

// output
45
28

为什么要用bufio来获取输入,因为用scanf、scan、scanln太慢,做题会超时。。。。

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	var n, m int
	var a = [4][4]int{}
	fmt.Scan(&n, &m)

	input := bufio.NewScanner(os.Stdin)
	for i := 1; i <= 3; i++ {
		input.Scan()
		line := strings.Split(input.Text(), " ") // 用.Text()方法获取输入内容,这里用了Split再切割了
		for j := 1; j <= 3; j++ {
			a[i][j], _ = strconv.Atoi(line[j-1])
		}
	}
	fmt.Println(a)
}

// 输入
3 3
1 2 3
1 2 3
1 2 3
// 输出
[[0 0 0 0] [0 1 2 3] [0 1 2 3] [0 1 2 3]]

注意事项

总结: 使用 bufio.NewScanner 读取输入,注意以下

bufio.NewScanner的底层buf数组有个最大缓存限制的,是64K,也就是说按照标准的Scan,一行最多64K的数据大小,题目里如果超过这个范围,比如一行20万数据,每个数据范围还是int32内的,那这就至少800K的大小了,还没算上中间的空格,所以默认的buf空间肯定是不够的,这时候需要调用Buffer方法,手动给Scanner分配一个满足题目空间的buf数组,其余照常。使用方法如下:

sc := bufio.NewScanner(os.Stdin) // 实例化 NewScanner
bs := make([]byte, 2000*1024) // 缓存
sc.Buffer(bs, len(bs))
sc.Scan() // Scan 方法 该方法好比 iterator 中的 Next 方法,默认ScanLines 返回一行文本,不包括行尾的换行符
fmt.Println(sc.Text()) // 该方法应该在 Scan 调用后调用.Text 返回的是 string




// 实例
func main() {
	var n, m int
	var a = [4][4]int{}
	fmt.Scan(&n, &m)

	input := bufio.NewScanner(os.Stdin)
	bs := make([]byte, 2000*1024)    // 区别就这两行
	input.Buffer(bs, len(bs))       // 区别就这两行
	for i := 1; i <= 3; i++ {
		input.Scan()
		line := strings.Split(input.Text(), " ") // 用.Text()方法获取输入内容,这里用了Split再切割了
		for j := 1; j <= 3; j++ {
			a[i][j], _ = strconv.Atoi(line[j-1])
		}
	}
	fmt.Println(a)
}

AcWing 796. 子矩阵的和

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    const N = 1010
    var n, m, q int
    var a = [N][N]int{}
    var s = [N][N]int{}

    fmt.Scanf("%d%d%d", &n, &m, &q)

    scanner := bufio.NewScanner(os.Stdin) // 实例化 Scanner

    for i := 1; i <= n; i++ {
        scanner.Scan() // Scan 方法 该方法好比 iterator 中的 Next 方法
        line := strings.Split(scanner.Text(), " ")
        for j := 1; j <= m; j++ {
            a[i][j], _ = strconv.Atoi(line[j-1])
        }
    }

    for i := 1; i <= n; i++ {
        for j := 1; j <= m; j++ {
            s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j] // 求前缀和
        }
    }

    var x1, y1, x2, y2 int
    var ll [4]int

    for q > 0 {
        q--
        scanner.Scan()
        temp := strings.Split(scanner.Text(), " ")
        for i, s := range temp {
            ll[i], _ = strconv.Atoi(s)
        }
        x1, y1, x2, y2 = ll[0], ll[1], ll[2], ll[3]

        fmt.Printf("%d\n", s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]) // 算子矩阵的和
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值