Skip to content

競程常用的「高速輸入 、集中輸出」

以下程式碼是做什麼用的?

import sys
data = sys.stdin.read().split()
out = []
idx = 0


print("\n".join(out))  # 注意,out 裡面要是字串,也就是他要是字串組成的 list

1. 這兩個是競程常用的「高速輸入 / 集中輸出」

你問的兩段:

import sys

data = sys.stdin.read().split()

和:

print("\n".join(out))

可以把它們理解成:

一次把所有輸入讀進來
一次把所有輸出印出去

這在 UVA / CPE 很常用,因為比一直 input()、一直 print() 更穩、更快。


2. import sys 是什麼?

import sys

意思是載入 Python 的 sys 模組。

在競程裡,我們常用它來做:

sys.stdin.read()

也就是直接讀取所有標準輸入。

可以先把 sys.stdin 想成:

使用者輸入進來的整包資料

3. sys.stdin.read() 是什麼?

假設輸入是:

3
123 456
555 555
0 0

如果寫:

text = sys.stdin.read()
print(text)

text 會是整包字串:

"3\n123 456\n555 555\n0 0\n"

其中 \n 代表換行。


4. .split() 是什麼?

data = sys.stdin.read().split()

這行會做兩件事:

1. sys.stdin.read():把全部輸入讀成一整個字串
2. .split():用空白、換行、Tab 把字串切開

例如輸入:

123 456
555 555
0 0

執行:

data = sys.stdin.read().split()

得到:

["123", "456", "555", "555", "0", "0"]

注意,裡面的東西都是 str,不是 int

所以要用時通常要轉型:

a = int(data[0])
b = int(data[1])

5. 為什麼它適合 UVA 10035?

UVA 10035 的輸入長這樣:

123 456
555 555
123 594
0 0

用:

data = sys.stdin.read().split()

會變成:

["123", "456", "555", "555", "123", "594", "0", "0"]

我們就可以兩個兩個拿:

idx = 0

while idx < len(data):
    a = int(data[idx])
    b = int(data[idx + 1])
    idx += 2

也就是:

第一次拿 data[0], data[1] → 123, 456
第二次拿 data[2], data[3] → 555, 555
第三次拿 data[4], data[5] → 123, 594
第四次拿 data[6], data[7] → 0, 0

6. out = [] 是什麼?

通常我們會先準備一個 list:

out = []

然後不要馬上 print(),而是把答案先放進去:

out.append("No carry operation.")
out.append("3 carry operations.")
out.append("1 carry operation.")

此時:

out

大概會長這樣:

[
    "No carry operation.",
    "3 carry operations.",
    "1 carry operation."
]

7. "\n".join(out) 是什麼?

"\n".join(out)

意思是:

用換行符號 "\n" 把 out 裡面的每個字串接起來

例如:

out = [
    "No carry operation.",
    "3 carry operations.",
    "1 carry operation."
]

print("\n".join(out))

等於印:

No carry operation.
3 carry operations.
1 carry operation.

中間每一項都用換行隔開。


8. join() 的小例子

a = ["apple", "banana", "cat"]

print(" ".join(a))

輸出:

apple banana cat

因為用空白 " " 連接。


a = ["apple", "banana", "cat"]

print("-".join(a))

輸出:

apple-banana-cat

因為用 "-" 連接。


a = ["apple", "banana", "cat"]

print("\n".join(a))

輸出:

apple
banana
cat

因為用換行 "\n" 連接。


9. 注意:join() 只能接字串

這樣可以:

out = ["1", "2", "3"]
print("\n".join(out))

但這樣不行:

out = [1, 2, 3]
print("\n".join(out))

因為 join() 只能接 str

如果是數字,要先轉字串:

out = [1, 2, 3]
out = list(map(str, out))

print("\n".join(out))

輸出:

1
2
3

或者一開始就 append 字串:

out.append(str(ans))

10. 跟 input() / print() 寫法比較

10.1 一般寫法

while True:
    a, b = map(int, input().split())

    if a == 0 and b == 0:
        break

    print(a + b)

這樣很好懂。


10.2 競程高速寫法

import sys

data = sys.stdin.read().split()
out = []

idx = 0

while idx < len(data):
    a = int(data[idx])
    b = int(data[idx + 1])
    idx += 2

    if a == 0 and b == 0:
        break

    out.append(str(a + b))

print("\n".join(out))

這樣比較快,適合大量輸入輸出。


11. 什麼時候適合用 sys.stdin.read().split()

適合:

輸入格式很規律
不需要保留整行空白
每個資料用空白或換行隔開
題目資料量大

例如:

整數很多
每筆測資固定幾個數字
輸入到 EOF
輸入到 0 0 結束

像 UVA 10035、UVA 299、很多 CPE 題都適合。


12. 什麼時候不要用 .split()

如果題目需要保留空白,就不要用:

sys.stdin.read().split()

例如 UVA 490 Rotating Sentences。

因為 .split() 會把空白吃掉。

UVA 490 這種題目要用:

lines = sys.stdin.read().splitlines()

splitlines() 會照行切,不會把行內空白切掉。

例如輸入:

A B
 C

用:

sys.stdin.read().split()

會得到:

["A", "B", "C"]

空白位置全部不見。

但用:

sys.stdin.read().splitlines()

會得到:

["A B", " C"]

行內空白會保留。


13. 你可以先背兩個模板

13.1 不需要保留空白

import sys

data = sys.stdin.read().split()

適合整數題、字串 token 題。


13.2 需要保留每一行原樣

import sys

lines = sys.stdin.read().splitlines()

適合文字處理、空白有意義的題。


14. 完整模板:輸入到 EOF

例如每行兩個數字,讀到 EOF:

import sys

data = sys.stdin.read().split()
out = []

for i in range(0, len(data), 2):
    a = int(data[i])
    b = int(data[i + 1])

    out.append(str(a + b))

print("\n".join(out))

15. 完整模板:輸入到 0 0 結束

import sys

data = sys.stdin.read().split()
out = []

idx = 0

while idx < len(data):
    a = int(data[idx])
    b = int(data[idx + 1])
    idx += 2

    if a == 0 and b == 0:
        break

    out.append(str(a + b))

print("\n".join(out))

16. 完整模板:第一個數字是測資數 T

import sys

data = sys.stdin.read().split()
t = int(data[0])
idx = 1
out = []

for _ in range(t):
    n = int(data[idx])
    idx += 1

    # 根據題目繼續讀資料
    out.append(str(n))

print("\n".join(out))

17. 總結

這行:

data = sys.stdin.read().split()

就是:

把全部輸入一次讀完,切成一格一格的字串資料

這行:

print("\n".join(out))

就是:

把所有答案一次用換行接起來印出

你之後可以先這樣判斷:

空白不重要 → 用 read().split()
空白很重要 → 用 read().splitlines()
輸出很多行 → 先 out.append(...),最後 print("\n".join(out))