#7: DNA大轉錄:IO 優化


nevikw39 ($\mathscr{nevikw}\pmb{39}\in\m...)

學校 : 一中
編號 : 4
來源 : [140.114.207.96]
最後登入時間 :
2023-02-14 20:37:38
c005. Ⅴ. DNA大轉錄 -- 台大資工二階 | From: [162.158.243.120] | 發表日期 : 2020-06-13 23:47

本題改自 112 CS a.k.a. 台大資工 2014 年二階程式題(ZeroJudge e934: pD. DNA 轉錄)。當然,原題沒有那麼噁心喇 XDD

本題貌似非常單純,乍看之下無論用 switch-case 或 map 都可以秒殺。然而字串長度最高達 $20000000$,此時字串的讀取及儲存或成為問題。不過,普通解應可獲得 90% 分數。

那麼這時我們就需要針對輸出入進行優化。

傳統刻板印象中,C++ 的 cin, cout 等「流」的操作往往被認為是慢於 的 printf(), scanf(),有兩大原因:

  1. cin, cout 預設與 stdio 同步,故可藉由 ios::sync_with_stdio(false) 來加速
  2. 一般情境中,終端機的輸出入是混合的,所以 cin 會與 cout 綁定以防止輸出被蓋過。但競賽中,兩者是分開的檔案,因此可利用 cin.tie(nullptr) 來加速
  3. 此外 endl 其實是先 put 一個 ‘\n’ 再 flush,在競賽中也是不必要的

理論上 cin, cout 應該略快,因為 template 在編譯時期就已經決定,反觀 scanf(), printf() 在執行時期才處理 format string。

當然,使用 getchar(), putchar() 每次讀取單個字元會更快。

此外,Linux 可以在原有 C 的 IO 函式後方加上 "_unlocked" 以呼叫非標準的執行緒不安全版本,例如 getchar_unlocked(), putchar_unlocked()

其他邪門歪道的技巧(?)像是一次 fread_unlocked() 一堆字元的頂多 #8 從 3ms 變為 2ms,整體影響不大。nmap 之類的我不會,看有迷有人要研究一下囉 o'_'o

以下簡表列出各種優化的費時供參:

 

Time (#9, #8)

cin, cout

TLE, 58ms

printf(), scanf()

TLE, 5ms

sync_with_stdio(false) | cin.tie(nullptr) cin.get(), cout

0.9s, 5ms

getchar(), cout

0.8s, 5ms

scanf(), putchar()

0.7s, 4ms

sync_with_stdio(false) & cin.tie(nullptr) cin.get(), cout

0.7s, 4ms

getchar(), putchar()

0.5s, 3ms

fread(), putchar()

0.4s, 3ms

getchar_unlocked(), putchar_unlocked()

0.2s, 3ms

以上是 c005 的題解,謝謝大家。

 
ZeroJudge Forum