最近看到洛谷上面有乙個讀入優化的**:
inline char get_char()說實話第乙個函式get_char的第二行,這麼長一六三目運算子真心看不懂inline
short
read()
(下面的read函式裡面那個isspace()和isdigit()就是判斷這個字元是不是空格,是不是數字,是的就返回true,不是返回false。你看多沒用的函式= =)
inline char nc(void)於是研究了一會,發現這是乙個極其神奇的讀入優化return *p1++;
}
一般來說我們讀入都用的scanf和cin,實在必要的時候可以用getchar讀入優化。
然後眾所周知,cin比scanf慢,getchar最快。
但是到底差距有多大很多人都不知道。
於是上個星期我做了乙個賊有意思的測試,把scanf、cin、getchar(分為巨集定義函式和內聯函式兩個)分別讀入1000000個數,然後輸出執行時間。
getchar的兩個函式貼在這裡:
#define gi(a) do發現scanf大概比cin快2倍,getchar比cin快5倍。while(0
)inline
void gi2(int &a)
//(僅限正整數)
其中巨集定義的getchar稍稍比內聯的getchar快那麼一點點點點。
然後就是今天我看到的玄學優化了。
這裡有所有讀入的速度評估(看來我還不是第乙個幹這種賊有意思的事情的wwww)
經過實測,這種優化比scanf快了10倍!
函式原型是這樣的:
size_t fread ( void *buffer, size_t size, size_t count, file *stream) ;可以看到有四個引數,分別是讀入的陣列,讀入每個資料項的位元組數,讀入的個數,以及讀入的檔案stream。
返回的是讀到的資料項的個數。
此外還有個static關鍵字,就把它看成是函式裡面的全域性變數就行了,也就是說再用一次這個函式,裡面的值不會變的。
此外static只有在第一次定義的時候才能賦值,之後呼叫的時候賦值是無效的,也就是說之後的呼叫函式這個賦值那一行是沒用的。
這裡還有個點,看這一行:
p2 = (p1 = buf) + fread(buf, 1, 100000, stdin);這裡的=號的返回值就是賦值號右邊的那個值,也就是buf的值。
那麼就等於寫成這樣:
p1 =buf;在我們一開始呼叫函式的時候,p1 p2都被賦值為buf的陣列開始的位置,之後進入if語句,p2變成資料最後的位置(開始的位置+資料的長度 = 最後的位置)。p2 = buf+ fread(buf, 1, 100000, stdin);
然後隨著每次返回,p1都會往前面移動乙個,直到p1也遍歷到了最後的位置,p1 == p2
這時候再次進入if語句,然後同樣p2變成資料最後的位置,因為p1這時也是資料最後的位置了,所以p1照樣==p2,於是資料遍歷結束了,返回檔案結束符eof.
就這樣,完美模擬一次檔案讀寫~
然後把if語句簡化就變成了那個很長一六的三目運算子:
inline char get_char()可以把這個模板背一下,然後就直接套自己的getchar讀入優化模板了。
當然也可以把這裡面的static索性全部拿到外面去,變成全域性變數,然後做乙個巨集定義:
char buf[1000001],*p1=buf,*p2=buf;雖說這樣肯定比內聯函式快,但是因為巨集定義畢竟是機械式替換的……所以不保證不出玄學bug,慎用。(不過一般來說用我自己寫的模板不會有問題)#define get_char() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?eof:*p1++)
(其實我不會把只有一行語句的巨集用do while(0)封裝起來,所以只能打個括號完事)
這個優化雖然快是快,但是因為奇技淫巧……不保證不出bug,所以還是謹慎使用。
就當做普及乙個玄學優化吧。
這裡有乙個大神寫的整合版,大致原理是一樣的,不過**更簡單,而且讀入比我的又要快一倍(用的指標+一次性讀入所有的整數),**如下
const最後貼上我把這個玄學優化寫進我的玄學getchar裡面弄出的超級巨型玄學賊有意思奇技淫巧讀入優化int maxs = 60*1024*1024
;const
int maxn = 10000000
;char
buf[maxs];
intnumbers[maxn];
void analyse(char *buf,int len =maxs)
void
fread_analyse()
char buf[1000001],*p1=buf,*p2=buf;#define get_char() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?eof:*p1++)
#define gi(a) do
while(0)
git 奇技淫巧
例如 1.0.0 git tag a 1.0.0 m 1.0.0 版本的備註資訊.複製 git push origin tags 複製 例如 1.0.0 git tag d 1.0.0 複製 刪除遠端標籤需要先刪除本地標籤,再執行下面的命令 git push origin refs tags 1.0...
Noip前的大抱佛腳 奇技淫巧
set查詢前驅後繼multiset iterator iter s.insert x iter s.find x 返回迭代器 iter 前驅 int ans iter s.erase find x return ans 或者可以使用 lower bound 大於等於 upper bound 嚴格大於...
c 的奇技淫巧
關於陣列 數論演算法技巧 stl其他 while scanf d d n,m eof 等價於 while scanf d d n,m 2 前者eof為檔案結束符,較保險 後者 後的數字為輸入的變數的個數 不能只寫while scanf d d n,m 這樣無法結束讀入 wwq大佬教的,希望我不要和他...