最近碰到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输入神器!