三种读入方式(两种输入挂)速度比较

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

发表评论

邮箱地址不会被公开。 必填项已用*标注

请输入正确的验证码