竞赛编程:比scanf()/cin更快的整数数组输入方法?TLE问题求解
嘿,我太懂这种在竞赛里卡输入超时的憋屈感了!你已经用了#include <bits/stdc++.h>和ios_base::sync_with_stdio(false); cin.tie(NULL);这两个基础操作,但有时候这些还不够应付超大输入量的场景。下面给你分享几个更硬核的优化方法:
1. 手动实现快速读入函数(用getchar())
cin哪怕关了同步,底层还是有一些额外开销。直接用getchar()手动解析整数是最快的方式之一,因为它绕开了C++流的很多封装。比如写一个专门读int的函数:
inline int fast_read() { int res = 0, sign = 1; char ch = getchar(); // 跳过非数字字符,处理负号 while (ch < '0' || ch > '9') { if (ch == '-') sign = -1; ch = getchar(); } // 解析数字 while (ch >= '0' && ch <= '9') { res = res * 10 + (ch - '0'); ch = getchar(); } return res * sign; }
调用的时候直接int x = fast_read();,比cin >> x快很多,尤其是数据量达到1e6以上的时候。如果是无符号整数,可以去掉负号处理,速度还能再提一点。
2. 一次性读入整个输入缓冲区
磁盘IO是最耗时的环节之一,频繁调用getchar()或cin会多次触发IO操作。我们可以一次性把所有输入读到一个大的char缓冲区里,然后在内存里解析整数,彻底减少IO次数:
#include <cstdio> #include <cstring> // 定义一个足够大的缓冲区,比如1MB(1<<20字节) char input_buf[1 << 20]; int buf_ptr = 0; // 先把整个输入读到缓冲区 void load_input() { buf_ptr = 0; // fread会返回实际读入的字节数,这里忽略返回值(竞赛题输入不会空) fread(input_buf, 1, sizeof(input_buf), stdin); } // 从缓冲区里解析整数 inline int fast_read_from_buf() { int res = 0, sign = 1; // 跳过非数字 while (input_buf[buf_ptr] < '0' || input_buf[buf_ptr] > '9') { if (input_buf[buf_ptr] == '-') sign = -1; buf_ptr++; } // 解析数字 while (input_buf[buf_ptr] >= '0' && input_buf[buf_ptr] <= '9') { res = res * 10 + (input_buf[buf_ptr] - '0'); buf_ptr++; } return res * sign; }
使用前先调用load_input(),之后直接用fast_read_from_buf()读数据。这种方法在输入量极大(比如1e7级别)时优势特别明显。
3. 替换endl为'\n'
这个细节很容易被忽略!endl不仅会输出换行,还会强制刷新输出缓冲区,每次调用都会带来额外开销。如果你的代码里用了很多cout << endl;,全部换成cout << '\n';,能显著减少输出侧的耗时(有时候输入超时也可能是输出拖慢了整体速度)。
4. 用scanf/printf替代cin/cout
虽然你已经优化了cin,但scanf在极端情况下还是比优化后的cin快一点。比如读整数直接用scanf("%d", &x);,写法简单,速度也够快,适合不想写自定义函数的场景。不过要注意不要混合使用cin和scanf,否则会破坏同步设置,导致速度变慢。
5. 进阶:关闭更多流的额外检查
如果用cin,除了ios_base::sync_with_stdio(false); cin.tie(NULL);,还可以加上:
cin.tie(nullptr); ios::sync_with_stdio(false); cin.exceptions(ios::failbit | ios::badbit); // 可选,关闭错误检查(竞赛题输入一般合法)
关闭错误检查能进一步减少流的开销,但前提是你确定输入是完全合法的(竞赛题通常满足这点)。
这些方法里,自定义快速读入函数是最常用也最有效的,建议优先尝试。如果还是超时,再考虑一次性读入缓冲区的方案。
内容的提问来源于stack exchange,提问作者Shiva Chandel

