「黑科技」使用 streambuf 加速 iostream

使用 streambuf 使 cin / cout 效率高于 fread / fwrite。
iostream 翻身了!!!

iostream

作为一个 C++ 标准库,如果各项功能都赶不上 C 语言的 IO,那还要它有何用?
cin 和 cout 在 OI 中几乎是公认的慢了,但是这其实是使用的问题所造成的。

sync

首先解除 iostream 与 C IO 的绑定,然后解除 cin 与 cout 的绑定,这几个操作相信大家都知道了。

1
2
3
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);

streambuf

iostream 底层使用了 streambuf,也就是说 cin 和 cout 底层有流缓冲区,我们可以推测导致 cin / cout 慢的原因是对于各种类型的抽取与解析,事实上也是这样。

获取 streambuf

我们首先得拿到 iostream 的 streambuf。

rdbuf

rdbuf 方法返回当前 stream 的 streambuf。

1
std::streambuf *fb = std::cin.rdbuf();

输入

sgetc

sgetc 返回 streambuf 中的下一个字符,用法相当于 getchar,但效率甚至高于 getchar_unlocked。

1
char c = fb->sgetc();
sgetn

sgetn 读入 streambuf 中的 $n$ 个字符,作用等价于 fread,但效率甚至高于 fread_unlocked。

1
2
3
4
5
6
const int MAXN = 1000000;
char obuf[MAXN];
inline void input() {
fb->sgetn(obuf, MAXN);
}

输出

sputc

sputc 输出一个字符,用法相当于 putchar,但效率甚至高于 putchar_unlocked。

1
2
char c = 't';
fb->sputc(c);
sputn

sputn(buf, n) 输出 buf 中的 $n$ 个字符,作用等价于 fwrite,但效率甚至高于 fwrite_unlocked。

1
2
3
4
5
6
const int MAXN = 1000000;
char obuf[MAXN];
inline void output() {
fb->sputn(obuf, MAXN);
}

示例

LOJ 110

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* test std::streambuf and std::cout.rdbuf
* @author xehoth
*/
#include <bits/stdc++.h>
const int OUT_LEN = 10000000;
char obuf[OUT_LEN], *oh = obuf;
std::streambuf *fb;
inline void print(char c) {
oh == obuf + OUT_LEN ? (fb->sputn(obuf, OUT_LEN), oh = obuf) : 0;
*oh++ = c;
}
template <class T>
inline void print(T x) {
static int buf[30], cnt;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
while (cnt) print((char)buf[cnt--]);
}
inline void flush() { fb->sputn(obuf, oh - obuf); }
#define long long long
const int MAXN = 3000001;
int inv[MAXN];
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
fb = std::cout.rdbuf();
register int n, mod;
std::cin >> n >> mod;
inv[1] = 1;
for (int i = 2; i <= n; i++)
inv[i] = (long)(mod - mod / i) * inv[mod % i] % mod;
for (register int i = 1; i <= n; i++) print(inv[i]), print('\n');
flush();
return 0;
}

分享到