前言
卡常必备小技巧,妹妹除外。
读入
在萌芽时期,我们使用的朴实无华的读入是 scanf
。
后来有人用了更简便的 cin
但是他不关同步。
虽然关了同步的 cin
还是挺快的,但是不能和 scanf
之类的混用,容易引起问题。
所以我们就直接手写读入函数!
前置知识:getchar巨快!
于是我们可以写出这样一份快读:
LL Read()
{
LL x = 0,f = 1; char c = getchar();
while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
其中的 x*10
有人喜欢写成 (x<<3)+(x<<1)
,但本人亲测其实没多大区别,甚至 long long
类型和 int
类型的速度也没多大区别,所以这就是我最常用的读入。
但是有些时候,这还不够快,我们还需要优化!
fread!
char buf[1<<21];
char getChar(){
static char *S = buf, *T = S;
if(S == T) S = buf, T = S + fread(S,1,1<<21,stdin);
return *(S ++);
}
大概思路是它一次性把读入文件全部都读进来了,然后一个一个送出去,用上这个函数,再把上文的 Read
函数中的 getchar()
换成 getChar()
就好了。
运行速度可以甩 getchar()
版本十条街,缺点是只能用文件输入输出。
输出
我喜欢这么写:
#define TT template<typename T>
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
这个版本的快输可以自动识别输出类型,还可以在后面加个字符,比如这样:
Put(x);
Put(x,' ');
Put(x,'
');
但是与fread相应的,我们还有fwrite!
不会,等fread都不够用了再来填坑。