读入优化&输出优化 (C++) 详解
写在前面
本文主要介绍了C++读入和输出的一些性质和优化
希望对读者有所帮助
cin/cout
大家对这个应该很熟悉了吧?想必最开始接触 (OI) 的时候大家写的输入输出就是用的这个吧。
其实你做多了题目就会发现这个 (cin) 和 (cout) 是非常慢的,因为它从缓冲区中读入数据。
而这个缓冲常常是同步的,因为它还需要辨别输入类型。
为了加速这个东西,所以我们可以在代码中加入这样一句话,意为关闭同步流:
ios::sync_with_stdio(false);
然后再次使用 (cin) 和 (cout) 就会变得很快了。
但是在大量的数据面前,它的表现仍然不够出色,常常有 (TLE) 的存在。
scanf/printf
这个东西应该是大多数较为自身的(Oler) 在用的东西了。
因为它还要加上什么格式符而为广大初学者所不喜欢。
- 但是请注意:它很快!
但是它也有一个坏处,相信很多做过字符串题目的 (Oler) 应该清楚,这个scanf可能读入一个换行符!
这里解释下原因:(Linux) 和 (Windows) 下换行符是不一样的!
至于哪里不一样读者可以查阅网上资料,这里只做原因解释,因此如果读入字符且有换行之类,建议读一句
scanf("
");
然后就没有什么好说的了 (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('
');
}
里面运用(x=(x<<3)+(x<<1)+(c ext{^} 48))是因为位运算会快于四则远算。
至于这边可以采用 (c ext{^} 48=c-48),因为 (0) 的 二进制 下编码为 (48),你会发现 (0-9) 的 二进制表示 在 (48) 的二进制下表示刚好错开。
我们刚好可以利用这个性质进行优化,对于输出自然是一样。
- 它还不够快?
Superread()/Superwrite()
顾名思义,超级快读和超级快输。