保存按入场顺序排列的学号列表,把每个一号起始询问转换成 Python 列表下标。
OJ: luogu
题目 ID: P3156
难度:入门
标签:列表模拟python
日期: 2026-07-16 18:10
题意
按进教室顺序给出 n 个学号。每次询问第 i 个进入的学生学号,逐行输出答案。
思路
顺序固定且只查询位置,直接把学号按入场顺序存起来。题目编号从 1 开始,下标从 0 开始,因此查询 position 的答案是 student_ids[position-1]。
注意:n <= 2e6。若写成
python
data = list(map(int, sys.stdin.buffer.read().split()))会瞬间创建约 n+m 个 Python int 对象,常数很大,容易在大数据上 TLE / MLE,小样例仍正确,分数常停在 30 分左右。
更稳妥的做法:
sys.stdin.buffer.read().split()只得到bytestoken;- 学号用
array("i", ...)存成连续整型数组; - 查询时再
int(token),答案用"\n".join一次写出。
Python 知识
array("i")存 32 位有符号整数,比list[int]省对象开销。- 大数据输入优先
sys.stdin.buffer.read(),避免逐行input()。 "\n".join(...)比十万次print更适合批量输出。/home/rainboy/mycode/hugo-blog/content/program_language/python/oj_input_output_cheatsheet.md:大量整数 token 与多行输出。
代码
python
import sys
from array import array
data = sys.stdin.buffer.read().split()
n = int(data[0])
m = int(data[1])
# n 最大 2e6:用 array 存学号,避免 200 万个 Python int 对象拖慢
student_ids = array("i", map(int, data[2 : 2 + n]))
out = [str(student_ids[int(data[2 + n + i]) - 1]) for i in range(m)]
sys.stdout.write("\n".join(out))cpp
/**
* P3156 【深基15.例1】询问学号
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 5;
// 学号数组,按入场顺序存放,下标从 1 开始
int a[MAXN];
int n, m;
int main() {
scanf("%d%d", &n, &m);
// 读入 n 个学号
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
// 处理 m 次询问,题目编号从 1 开始,直接输出 a[query]
while (m--) {
int x;
scanf("%d", &x);
printf("%d\n", a[x]);
}
return 0;
}Pythonic 写法
下标查询生成器:
python
import sys
from array import array
data = sys.stdin.buffer.read().split()
n, m = map(int, data[:2])
ids = array("i", map(int, data[2 : 2 + n]))
sys.stdout.write("\n".join(str(ids[int(data[2 + n + i]) - 1]) for i in range(m)))复杂度
读入为
总结
先辨认操作需求:只有按位置查询时,连续列表就是最简单、最高效的数据结构。