在一些題目中會出現數據輸入很大的情況,如果我們運用不好讀取數據工具的話,那麼很可能會在讀取數據上花費較多的時間,甚至還沒讀完就超時了。
讀取速度
cin << scanf ≈ cin(關閉流同步) << getchar()
cin(關閉流同步)
爲什麼scanf的讀入數據的能力大於cin(未關閉流同步)?
C++中,cin和cout要默認與stdio同步。在cin、cout輸入輸出下,會有進行緩衝同步stdio,使scanf()與printf()能夠與cin、cout混用,也導致cin,cout語句輸入輸出緩慢。
cin關閉流的同步,就能夠實現使用cin、cout輸入輸出提速的效果(此時效果與scanf()、printf()差不多)。
std::ios::sync_with_stdio(false);
當未關閉流同步時,使用cin讀取一千萬個整數用了9.52秒。
當關閉流同步後,使用cin讀取一千萬個整數僅僅用了2.082秒。
讀取效率得到了顯著提高.
//關閉流同步
//data.txt中有一千萬個整數
#include<bits/stdc++.h>
const int MAXN = 10000000;
int numbers[MAXN];
int main()
{
int start = clock();
std::ios::sync_with_stdio(false);
freopen("data.txt","r",stdin);
for (int i=0;i<MAXN;i++)
std::cin >> numbers[i];
std::cout<<double(clock()-start)/CLOCKS_PER_SEC;
return 0;
}
當關閉流同步利弊:
利:在輸入n6級別的數據量情況下,相對於未關閉流同步的cin,關閉流的cin輸入效率得到提高。
弊:使用scanf()和printf()、getchar()來進行輸入或輸出的話,會造成輸入、輸出混亂的情況。
進一步提升效率
在cout和cin兩者同時使用的情況下,cin與cout需要交替操作,中間會有一個flush過程,會造成時間消耗。通過 cin.tie(0) 解除cin與cout的綁定,使flush過程不再執行(注意cout沒有tie方法)。另外,使用了endl之後,會對緩衝區執行清空操作。endl會先執行’\n’,再執行flush操作,非常漫長,所以儘量使用‘\n’而不是endl執行換行。
當關閉流同步後並解除cin與cout的綁定,使用cin讀取一千萬個整數用了1.981秒。
//解除
//data.txt中有一千萬個整數
#include<bits/stdc++.h>
const int MAXN = 10000000;
int numbers[MAXN];
int main()
{
std::cin.tie(0);
int start = clock();
std::ios::sync_with_stdio(false);
freopen("data.txt","r",stdin);
for (int i=0;i<MAXN;i++)
std::cin >> numbers[i];
std::cout<<double(clock()-start)/CLOCKS_PER_SEC;
return 0;
}
參考文章
關於std::ios::sync_with_stdio(false)
【輸入】極速讀取
getchar()
事實上,計算機處理char類型變量的速度會快於處理int類型變量。正好可以利用這點將輸入再進行一次提速。
下面提供一個簡易的快讀模板
//快讀:讀取一個整數
//getchar讀取效率比cin、scanf要高
int getInt()
{
char ch = getchar();
int x=0, f=1;
//符號位
while(ch<'0' || ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while('0'<=ch && ch<='9')
{
x = x*10+ch-'0';
ch=getchar();
}
return x*f;
}
希望將自己的學習經驗分享給有需要的人。
我是小鄭,一個堅持不懈的小白