跳转至

PIO7 多组_一维数组_T组形式

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

牛客原题  源码

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

一句话

t 组,每组先给长度 n,再给 n 个数,分别求和。

解题思路

这题考什么

输入形态:T 组形式 + 每组带前导数量。这是前面两种形态的组合, 也是本系列第一次必须真正用上前导数量 n 的题。

读入用一次性 read().split() 加游标 p 推进:读一个数就把 p 往前挪一格, 读一段数组就把 p 往前挪 n 格。p 始终指向「下一个还没被消费的 token」。

关键在于:一次性 split() 之后,token 流里再也没有「行」的概念了。 PIO6 之所以能无视 n,是因为它按行读,行边界天然把数组框了出来; 这里所有数字连成一片,唯一能告诉程序「这一组到哪里结束」的就是 n。 这就是前导数量存在的意义。

为什么不逐行 input()

t 最大 1e5,每组两行,总行数可达 2e5 + 1。逐行 input() 就是 2e5 次调用, 开销按次数累积;buffer.read() 无论多少行只读一次。 注意约束里 sum(n) <= 1e5,也就是数据本体其实很小, 大部分成本都花在「组」的固定开销上——这种题型对每组的调用次数最敏感。

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

数据规模与复杂度

t <= 1e5,sum(n) <= 1e5,a_i <= 1e9,单组的和最大 1e14。 时间 O(t + sum(n)),空间 O(t + token 总数)。

坑在哪

  1. p += n 不能漏。漏掉的话下一组会从上一组的数据中间开始读, 后面全部错位,且往往不报错,只是答案不对。
  2. data[p:p + n] 是列表切片,元素仍是 bytes;int() 能直接解析 bytes, 所以不需要 decode。只有当 token 要当字符串使用时才需要(见 PIO11)。
  3. n 读完立刻 p += 1,再用 p 去切数组——两处 p 的含义不同, 写在同一行时容易只加一次。

参考实现

solutions/PIO7.py
import sys

data = sys.stdin.buffer.read().split()
p = 0                                     # 游标:始终指向下一个未消费的 token
t = int(data[p]); p += 1                  # 消费组数
out = []
for _ in range(t):
    n = int(data[p]); p += 1              # 消费本组长度
    # token 流里没有行边界,只能靠 n 切出这一组的数据
    out.append(sum(map(int, data[p:p + n])))
    p += n                                # 跳过刚消费掉的 n 个数,指向下一组
sys.stdout.write("\n".join(map(str, out)) + "\n")
[:octicons-arrow-left-16: PIO6](PIO6.md) [PIO8 :octicons-arrow-right-16:](PIO8.md)