读入优化&输出优化 (C++) 详解

读入优化&输出优化 (C++) 详解

写在前面

本文主要介绍了C++读入和输出的一些性质和优化

希望对读者有所帮助

cin/cout

大家对这个应该很熟悉了吧?想必最开始接触 \(OI\) 的时候大家写的输入输出就是用的这个吧。

其实你做多了题目就会发现这个 \(cin\)\(cout\) 是非常慢的,因为它从缓冲区中读入数据。

而这个缓冲常常是同步的,因为它还需要辨别输入类型。

为了加速这个东西,所以我们可以在代码中加入这样一句话,意为关闭同步流:

ios::sync_with_stdio(false);

然后再次使用 \(cin\)\(cout\) 就会变得很快了。

但是在大量的数据面前,它的表现仍然不够出色,常常有 \(TLE\) 的存在。

scanf/printf

这个东西应该是大多数较为自身的\(Oler\) 在用的东西了。

因为它还要加上什么格式符而为广大初学者所不喜欢。

  • 但是请注意:它很快!

但是它也有一个坏处,相信很多做过字符串题目的 \(Oler\) 应该清楚,这个scanf可能读入一个换行符!

这里解释下原因:\(Linux\)\(Windows\) 下换行符是不一样的!

至于哪里不一样读者可以查阅网上资料,这里只做原因解释,因此如果读入字符且有换行之类,建议读一句

scanf("\n");

然后就没有什么好说的了 \(QAQ\)

  • **等等,你不是说这个很快嘛,我怎么呢在数据超过 \(100w\) 因为它而 \(TLE\) 了? **

因为它还不够快!

read()/output()

这两个函数就不要期望 C++ 还会给你配置了,为了更快的读入,只能手写了咯

原理:\(getchar()/putchar()\)速度较快。

我们按照高精度的方式,可以把数字当做字符读入/输出,最后再转化为数字,这样会更快。

  • **起码它在 \(100w\) 以上的数据量表现得很强势! **

那么我们模拟实现即可:

inline void read() {
	static bool f;
	static char c;
	static int x;
	
	while(!isdigit(c = getchar()) && c != '-');
	x = (f = c == '-') ? 0 : c ^ 48;
	while(isidit(c = getchar()))
		x = (x << 3) + (x << 1) + (c ^ 48);
	return f ? ~x + 1 : x;
}

inline void output(int x) {
#define reg register	
	static char buf[30], *tail = buf;
	if(x == 0) putchar('0');
	else {
		if(x < 0) x = ~x + 1, putchar('-');
		for(; x; x /= 10) *++tail = (x % 10) ^ 48;
		for(; tail != buf; --tail) putchar(*tail);
	} putchar('\n');
}

里面运用\(x=(x<<3)+(x<<1)+(c \text{^} 48)\)是因为位运算会快于四则远算。

至于这边可以采用 \(c \text{^} 48=c-48\),因为 \(0\) 的 二进制 下编码为 \(48\),你会发现 \(0-9\) 的 二进制表示 在 \(48\) 的二进制下表示刚好错开。

我们刚好可以利用这个性质进行优化,对于输出自然是一样。

  • 它还不够快?

Superread()/Superwrite()

顾名思义,超级快读和超级快输。

posted @ 2019-10-25 21:10  Ning-H  阅读(880)  评论(0编辑  收藏  举报