跳转至

PIO9 多组_二维数组_T组形式

入门通过率 75.15%python3样例通过牛客 AC

牛客原题  源码

讲解章节输入输出处理复杂度与 Python 性能

一句话

t 组,每组一个 n 行 m 列的矩阵,分别求和。

解题思路

这题考什么

输入形态:T 组形式 + 每组带两个前导数量。 结构与 PIO7 完全一致,只是每组要跳过的 token 数从 n 变成了 n * m。

仍然是「一次性读入 + 游标推进」:p 指向下一个未消费的 token, 每组先消费 n 和 m 两个数,再把随后的 n * m 个 token 求和,然后把 p 往前挪同样多。 矩阵的行列结构对求和无用,所以照例不建二维列表。

为什么必须一次性读入

t 最大 1e5,而 sum(n * m) 最大 1e6。两个上界放在一起看很有说明性: 数据本体只有一百万个数,但组数可达十万,也就是说很多组只有一两个元素。 这种「组多、每组小」的分布下,主导成本不是算术而是每组的固定开销—— 逐行 input() 要付出十万次以上的调用代价,一次 buffer.read() 只付出一次。

输出同理,t 行答案攒进 out 后 join 成一整块写出,只有一次输出调用。

数据规模与复杂度

t <= 1e5,n, m <= 1e3,sum(n * m) <= 1e6,元素 <= 1e9。 单组的和最大 1e6 * 1e9 = 1e15。时间 O(t + sum(n * m)),空间 O(token 总数)。

坑在哪

  1. 每组要跳过的是 n * m 而不是 n。少乘一个 m,后续所有组的读取位置全部错位, 而且不会报错,只会安静地给出错误答案。
  2. cnt 先算出来再用两次(切片上界与游标推进),保证两处一定一致; 两处各写一遍 n * m,改动时容易只改一处。
  3. 读完 n 和 m 之后 p += 2,不是 += 1。

参考实现

solutions/PIO9.py
import sys

data = sys.stdin.buffer.read().split()
p = 0                                     # 游标:始终指向下一个未消费的 token
t = int(data[p]); p += 1
out = []
for _ in range(t):
    n, m = int(data[p]), int(data[p + 1]); p += 2   # 一次消费两个数,故加 2
    cnt = n * m                           # 本组元素个数;切片与游标推进共用,避免两处写法不一致
    out.append(sum(map(int, data[p:p + cnt])))
    p += cnt                              # 跳过整个矩阵,指向下一组的 n
sys.stdout.write("\n".join(map(str, out)) + "\n")
[:octicons-arrow-left-16: PIO8](PIO8.md) [PIO10 :octicons-arrow-right-16:](PIO10.md)