index > Misc > Fast I/O
基本习惯
-
尽量
printf
/scanf
-
用
cin
/cout
的时候记得关同步ios::sync_with_stdio(false); cin.tie(nullptr);
-
关同步的
cin
/cout
不要和printf
/scanf
混用。 -
注意
endl
自带了fflush
,输出较慢。
虽然不一定很快,但是一般能过。
卡过时限——读入挂
有时候对自己的算法很有信心,觉得读入再快一点就肯定能过了。
于是就有人发明了各种各样的读入挂 ,但很少派上用场。
我就存了一个最可能用到,也比较好敲的读入挂。(尤其是现场赛的时候)
template <typename _Tp> inline _Tp read(_Tp&x){
char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
对于整数类型的变量a
,直接写read(a)
就行了。这也是常见的优化思路之一,通过读char来加速读入。
极致速度——现场绝缘
下面的轮子来自Fast and furious C++ I/O 可以从这里拷贝到,洋洋洒洒500多行,既然牺牲代码长度(可复现性),那么就一定要有极致的速度啦。
使用方法:
首先在main的开头,或者宏定义的开头,需要做输入输出指向的配置。(下面的代码自己选择一个input和output放进自己代码即可)
#ifdef ONLINE_JUDGE
input.reset(new InputFile(stdin, false)); // usual problem
input.reset(new InputFile()); // interactive problem
output.reset(new OutputFile());
#else
input.reset(new InputFile()); // local testing using a console
input.reset(new InputFile("input.txt")); // local testing using a file
output.reset(new OutputFile()); // output to console
output.reset(new OutputFile("output.txt")); // output to a file
#endif
然后你就可以在外挂下面写自己的实例,比如:
const int N = 1001;
int n, m;
char s[N][N];
int a[N], b[N];
int main() {
input.reset(new InputFile(stdin, false));
output.reset(new OutputFile());
read(n, m, s, n, a, n, b, m);
writeln(n, m, '\n', setDelimiter("\n"), s, n);
writeln(setDelimiter(", "), a, n, '\n', b, m);
return 0;
}
输入输出封装的都很完备,基本所有类型都支持(甚至std::string),在自己写的时候也会非常方便。
可以自己试试把原来的比较慢的代码加入这个黑科技来提交试试,体验愉悦。甚至会影响一个题的平衡,比如出题人不希望出现带log
的做法,但被这个外挂优化过去了。
注* 我自己测试好像__int128
是不行的。
#include <algorithm>
#include <cassert>
#include <complex>
#include <cstring>
#include <memory>
#include <string>
#include <vector>
using namespace std;
template <class T> struct is_iterator {
template <class U, typename enable_if<!is_convertible<U, const char*>::value, int>::type = 0>
constexpr static auto has_indirection(int) -> decltype(*declval<U>(), bool()) {
return true; }
template <class> constexpr static bool has_indirection(long) {
return false; }
constexpr static bool value = has_indirection<T>(0);
};
using uint = unsigned int;
// Buffer size should be 2^12 or 2^13 for optimal performance with files.
const uint BUFFER_SIZE = 1 << 12;
// Maximum possible length of a string representing primitive type
// assuming we won't encounter huge double values.
const uint MAX_LENGTH = 1 << 7;
namespace Detail {
struct Width {
uint value; };
struct Fill {
char value; };
struct Base {
uint value; };
struct Precision {
uint value; };
struct Delimiter {
const char* value; };
} // namespace Detail
Detail::Width setWidth(uint value = 0) {
return {
value}; }
Detail::Fill setFill(char value = ' ') {
return {
value}; }
Detail::Base setBase(uint value = 10) {
assert(2 <= value && value <= 36); return {
value}; }
Detail::Precision setPrecision(uint value = 9) {
assert(value < MAX_LENGTH); return {
value}; }
Detail::Delimiter setDelimiter(const char* value = " ") {
return {
value}; }
/******************************* input classes ********************************/
class InputDevice {
protected:
const char* head;
const char* tail;
InputDevice(const char* head, const char* tail) : head(head), tail(tail), base(setBase().value) {
}
virtual void fillInput() = 0;
inline char nextChar() {
if (__builtin_expect(head >= tail, false)) fillInput();
return *head++;
}
template <class I> int readUnsignedIntGeneral(I& arg, char c) {
I value = 0;
int length = 0;
for (;; ++length, c = nextChar()) {
if (isDigit(c)) c -= '0';
else if (isUpper(c)) c -= 'A' - 10;
else if (isLower(c)) c -= 'a' - 10;
else c = base;
if (c >= base) break;
value = base * value + c;
}
arg = value;
return --head, length;
}
template <class I> inline int readUnsignedInt(I& arg, char c) {
if (__builtin_expect(base > 10, false)) return readUnsignedIntGeneral(arg, c);
I value = 0;
int length = 0;
for (; static_cast<unsigned char>(c - '0') < base; ++length, c = nextChar())
value = base * value + c - '0';
arg = value;
return --head, length;
}
template <class I> inline bool readSignedInt(I& arg, char c) {
bool negative = c == '-';
if (negative) c = nextChar();
typename make_unsigned<I>::type unsignedArg;
if (readUnsignedInt(unsignedArg, c) == 0) return false;
arg = negative ? ~static_cast<I>(unsignedArg - 1) : static_cast<I><