生活随笔
收集整理的這篇文章主要介紹了
ACM入门之【读入、输出优化】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文主要是基于oiwiki的做的總結,未來也會做一系列的相關文章。如果想繼續看的話可以關注專欄。 做這個專欄的目的是因為自己最近開始系統的再打一下基礎。于是想寫一個專欄便于喜愛ACM的初學者入門。
目錄 為啥要讀入、輸出優化 優化方法一: 關閉同步/解除綁定 優化方法二: 快讀、快寫 各種情況下的時間對比 總的模板
為啥要讀入、輸出優化
其實,讀入、輸出優化的目的就是防止我們因為讀入、輸出的問題使我們的程序TLE。于是我們需要讀入、輸出優化。 來減少我們的運行時間,達到AC題目的目的。
那么對于每道題我們是否需要必須進行讀入、輸出優化呢?
答:其實,這個其實是根據具體的題目來分析的。如果題目的輸入/輸出的數據很多(例如:1e5以上)那么保險起見是要加上優化的。 當然其實根據很多高手的習慣他們是不管題目的輸入/輸出多不多,直接加上優化的。
優化方法一: 關閉同步/解除綁定
scanf printf 的速度 是比 cin cout 的速度快很多的。 這是因為:C++ 為了兼容 C,保證程序在使用了 printf scanf 和 cin cout的時候不發生混亂,將輸入/輸出流綁到了一起,故時間就慢了很多。 解決辦法如下:
std::ios::sync_with_stdio(false); 這個函數是一個“是否兼容 stdio的開關,C++ 為了兼容 C,保證程序在使用了 printf 和 cout的時候 不發生混亂,將輸出流綁到了一起。 這其實是 C++ 為了兼容而采取的保守措施。我們可以在進行 IO 操作之前將 stdio 解除綁定,但是在這樣做之后 要注意不能同時使用 cin cout 和 printf scanf tie tie是將兩個stream綁定的函數,空參數的話返回當前的輸出流指針。 在默認的情況下 s t d : : c i n 綁定的是 s t d : : c o u t ,每次執行 < < 操作符的時候都要調用 f l u s h ( ) ,這樣會增加IO 負擔。可以通過 s t d : : c i n . t i e ( 0 ) (0 表示 NULL)來解除 s t d : : c i n 與 s t d : : c o u t 的綁定,進一步加快執行效率。
那么總的優化代碼如下:
std
:: ios
:: sync_with_stdio ( false ) ;
std
:: cin
. tie ( 0 ) ;
優化方法二: 快讀、快寫
scanf 和 printf 依然有優化的空間。注意: 這里的快讀、快寫只是針對整數,浮點數的話自行編寫。 原理 眾所周知, getchar是用來讀入 1 byte 的數據并將其轉換為 char 類型的函數,且速度很快,故可以用“讀入字符——轉換為整型”來代替緩慢的讀入每個整數由兩部分組成——符號和數字整數的’+’ 通常是省略的,且不會對后面數字所代表的值產生影響,而’-’ 不可省略,因此要進行判定10 進制整數中是不含空格或除 0~9 和正負號外的其他字符的,因此在讀入不應存在于整數中的字符(通常為空格)時,就可以判定已經讀入結束C 和 C++ 語言分別在 ctype.h 和 cctype 頭文件中,提供了函數isdigit , 這個函數會檢查傳入的參數是否為十進制數字字符,是則返回 true,否則返回 false。對應的,在下面的代碼中,可以使用 isdigit(ch) 代替 ch > = ' 0 '& & ch<= ' 9 ' , 而可以使用 ! isdigit(ch)代替 c h < ' 0 ' | | c h > ' 9 ' 那么模板如下:
template < typename T >
inline T
read ( )
{ T sum
= 0 , fl
= 1 ; int ch
= getchar ( ) ; for ( ; ! isdigit ( ch
) ; ch
= getchar ( ) ) if ( ch
== '-' ) fl
= - 1 ; for ( ; isdigit ( ch
) ; ch
= getchar ( ) ) sum
= sum
* 10 + ch
- '0' ; return sum
* fl
;
}
template < typename T >
inline void write ( T x
)
{ static int sta
[ 35 ] ; int top
= 0 ; do { sta
[ top
++ ] = x
% 10 , x
/= 10 ; } while ( x
) ; while ( top
) putchar ( sta
[ -- top
] + 48 ) ;
}
使用方法如下:
a
= read
< int > ( ) ;
b
= read
< long long > ( ) ;
c
= read
< __int128
> ( ) ;
write ( a
) ;
各種情況下的時間對比
通過上圖你基本會有一個大致的認知了。最后還可以加上火車頭來進一步的優化。加上火車頭以后,我們的時間又會少了點。 火車頭代碼如下:
# pragma GCC optimize ( 2 )
# pragma GCC optimize ( 3 )
# pragma GCC optimize ( "Ofast" )
# pragma GCC optimize ( "inline" )
# pragma GCC optimize ( "-fgcse" )
# pragma GCC optimize ( "-fgcse-lm" )
# pragma GCC optimize ( "-fipa-sra" )
# pragma GCC optimize ( "-ftree-pre" )
# pragma GCC optimize ( "-ftree-vrp" )
# pragma GCC optimize ( "-fpeephole2" )
# pragma GCC optimize ( "-ffast-math" )
# pragma GCC optimize ( "-fsched-spec" )
# pragma GCC optimize ( "unroll-loops" )
# pragma GCC optimize ( "-falign-jumps" )
# pragma GCC optimize ( "-falign-loops" )
# pragma GCC optimize ( "-falign-labels" )
# pragma GCC optimize ( "-fdevirtualize" )
# pragma GCC optimize ( "-fcaller-saves" )
# pragma GCC optimize ( "-fcrossjumping" )
# pragma GCC optimize ( "-fthread-jumps" )
# pragma GCC optimize ( "-funroll-loops" )
# pragma GCC optimize ( "-fwhole-program" )
# pragma GCC optimize ( "-freorder-blocks" )
# pragma GCC optimize ( "-fschedule-insns" )
# pragma GCC optimize ( "inline-functions" )
# pragma GCC optimize ( "-ftree-tail-merge" )
# pragma GCC optimize ( "-fschedule-insns2" )
# pragma GCC optimize ( "-fstrict-aliasing" )
# pragma GCC optimize ( "-fstrict-overflow" )
# pragma GCC optimize ( "-falign-functions" )
# pragma GCC optimize ( "-fcse-skip-blocks" )
# pragma GCC optimize ( "-fcse-follow-jumps" )
# pragma GCC optimize ( "-fsched-interblock" )
# pragma GCC optimize ( "-fpartial-inlining" )
# pragma GCC optimize ( "no-stack-protector" )
# pragma GCC optimize ( "-freorder-functions" )
# pragma GCC optimize ( "-findirect-inlining" )
# pragma GCC optimize ( "-fhoist-adjacent-loads" )
# pragma GCC optimize ( "-frerun-cse-after-loop" )
# pragma GCC optimize ( "inline-small-functions" )
# pragma GCC optimize ( "-finline-small-functions" )
# pragma GCC optimize ( "-ftree-switch-conversion" )
# pragma GCC optimize ( "-foptimize-sibling-calls" )
# pragma GCC optimize ( "-fexpensive-optimizations" )
# pragma GCC optimize ( "-funsafe-loop-optimizations" )
# pragma GCC optimize ( "inline-functions-called-once" )
# pragma GCC optimize ( "-fdelete-null-pointer-checks" )
不推薦使用火車頭,正式的比賽好像都不讓用。
總的模板
通過上文,可以得到以下幾種模板。 模板一: 快讀、快寫
好處: 我們可以cin cout printf scanf 混著用 壞處:模板有點長
template < typename T >
inline T
read ( )
{ T sum
= 0 , fl
= 1 ; int ch
= getchar ( ) ; for ( ; ! isdigit ( ch
) ; ch
= getchar ( ) ) if ( ch
== '-' ) fl
= - 1 ; for ( ; isdigit ( ch
) ; ch
= getchar ( ) ) sum
= sum
* 10 + ch
- '0' ; return sum
* fl
;
}
template < typename T >
inline void write ( T x
)
{ static int sta
[ 35 ] ; int top
= 0 ; do { sta
[ top
++ ] = x
% 10 , x
/= 10 ; } while ( x
) ; while ( top
) putchar ( sta
[ -- top
] + 48 ) ;
}
模板二: 關閉緩沖區和同步
好處: 優化的代碼很短,只需兩行 壞處: 優化后只可以cin cout
std
:: ios
:: sync_with_stdio ( false ) ;
std
:: cin
. tie ( 0 ) ;
個人推薦: 我一般喜歡不用模板,一般將輸入數據多的,輸出數據多的語句用scanf printf即可。 如果是打線上的一些比賽(例如 cf),會用第一種方法因為當要一些格式化的輸出時我喜歡用printf。
總結
以上是生活随笔 為你收集整理的ACM入门之【读入、输出优化】 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。