最近碰到HDU5289这题,发现输入变成了性能瓶颈,所以来比较一下三种输入方式的时间差异。
首先用下面的程序随机生成了10^6个long long范围的正负整数。
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> #include <ctime> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f; int main() { #ifdef SHY freopen("d:\\1.txt", "w", stdout); #endif srand(time(0)); repe(i,1,1000000) { LL a = rand()*rand()*(rand()&1?1:-1), b = rand()*rand()*(rand()&1?1:-1); printf("%I64d %I64d\n", a*a,b*b); } return 0; }
下面通过三种输入方式比较输入所花的时间:
【一,scanf读入】耗时820ms左右
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> #include <ctime> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 1000000; LL a[MAXN],b[MAXN]; int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif LL st = clock(); rep(i,0,MAXN) scanf("%I64d %I64d", &a[i], &b[i]); LL ed = clock(); printf("scanf :%I64d\n", ed-st); return 0; }
【二,getchar输入挂】耗时竟然达到了1700ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> #include <ctime> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 1000000; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } LL a[MAXN],b[MAXN]; int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif LL st = clock(); rep(i,0,MAXN) rd(a[i]),rd(b[i]); LL ed = clock(); printf("getchar :%I64d\n", (ed-st)); return 0; }
【三,fread输入挂】耗时只有330ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> #include <ctime> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 1000000; char buf[MAXN], *ps = buf, *pe = buf+1; inline void rnext(){ if(++ps == pe) pe = (ps = buf)+fread(buf,1,sizeof(buf),stdin); } template <class T> inline bool in(T &ans) { ans = 0; T f = 1; if(ps == pe) return false; do{ rnext(); if('-' == *ps) f = -1; }while(!isdigit(*ps) && ps != pe); if(ps == pe) return false; do { ans = (ans<<1)+(ans<<3)+*ps-48; rnext(); }while(isdigit(*ps) && ps != pe); ans *= f; return true; } LL a[MAXN],b[MAXN]; int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif LL st = clock(); rep(i,0,MAXN) in(a[i]),in(b[i]); LL ed = clock(); printf("fread :%I64d\n", ed-st); return 0; }
本机配置:
操作系统 Microsoft Windows 8.1 专业版 (64位)
CPU (英特尔)Intel(R) Core(TM) i7-3537U CPU @ 2.00GHz(2001 MHz)
主板 索尼 VAIO
内存 8.00 GB ( )
主硬盘 250 GB ( 三星固态硬盘 850 EVO 已使用时间: 980小时)
在Codeblock13.12自带的MINGW(G++4.8.1)下,三种输入的耗时分别是【一】759ms,【二】400ms,【三】330ms
然而HDU5289这一题使用单调队列用G++提交三种输入方式的速度分别是【一】343ms,【二】483ms,【三】46ms(惊人的达到了rank1)
C++提交为:【一】514ms,【二】436ms,【三】312ms
【总结】
无论如何使用fread的输入挂肯定会提高速度,而且非常明显。
而使用getchar的输入挂不太稳定,甚至有时候会比scanf慢。
所以建议使用fread输入神器!