输入输出优化
\(C++\) 库里有很多种输入与输出方式,我们最常用的是 \(scanf\) , \(printf\) 和 \(cin\) , \(cout\) 。除此之外,其它常见的还有: \(getchar\) , \(putchar\) , \(gets\) , \(puts\) , \(fgets\) , \(fputs\) , \(getline\) 等等。当输入或输出的数据量过大时,选择效率更高的输入与输出方式将为我们的程序运行节省不少时间。
基本原理
一般来说,在输入的效率方面,有 \(cin<<scanf<cin(关闭同步流)<<getchar\) ,具体情况还要看评测环境。不过, \(getchar\) 的效率往往比 \(cin\) 和 \(scanf\) 高得多,因此,基于 \(getchar\) , \(putchar\) 的输入输出优化应运而生。
效率分析
在绝大多数情况下,普通的输入输出优化已足以解决问题。然而,依然有极少数的题目会卡掉普通的输入输出优化。这时,需要使用比 \(getchar\) , \(putchar\) 更快的 \(fread\) , \(fwrite\) 。
核心代码
简易版
整数的输入输出优化。
templateinline bool read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c)){if(c==EOF)return false;f^=c=='-',c=getchar();}
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
return true;
}
templateinline void print(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
templateinline void print(T x,char c){print(x),putchar(c);}
普通版
整数、浮点数、字符、字符数组、字符串的输入输出优化。
templateinline bool read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c)){if(c==EOF)return false;f^=c=='-',c=getchar();}
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
return true;
}
templateinline bool readd(T &x)
{
register ll X=0;register double y=1.0;register char c=getchar();register bool f=0;
while(!isdigit(c)){if(c==EOF)return false;f^=c=='-',c=getchar();}
while(isdigit(c))X=(X<<3)+(X<<1)+(c^48),c=getchar();
x=X;
if(c!='.')return true;
c=getchar();
while(isdigit(c))x+=(y/=10)*(c^48),c=getchar();
if(f)x=-x;
return true;
}
templateinline bool readc(T &x)
{
register char c=getchar();
while(c==' '||c=='\n'||c=='\r'||c=='\t')c=getchar();
if(c==EOF)return false;
x=c;
return true;
}
templateinline bool readc(T *x)
{
register char c=getchar();
while(c==' '||c=='\n'||c=='\r'||c=='\t')c=getchar();
if(c==EOF)return false;
while(c!=' '&&c!='\n'&&c!='\r'&&c!='\t'&&c!=EOF)*x++=c,c=getchar();
*x=0;
return true;
}
templateinline bool reads(T &x)
{
x="";register char c=getchar();
while(c==' '||c=='\n'||c=='\r'||c=='\t')c=getchar();
if(c==EOF)return false;
while(c!=' '&&c!='\n'&&c!='\r'&&c!='\t'&&c!=EOF)x+=c,c=getchar();
return true;
}
templateinline void print(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
templateinline void printd(T x,ll y)
{
static ll mul[]={1};
for(register ll i=1;i<=18;i++)
mul[i]=(mul[i-1]<<3)+(mul[i-1]<<1);
if(x<-1e-12)putchar('-'),x=-x;
x*=mul[y];
register ll x1=(ll)round(x),x2=x1/mul[y],x3=x1-x2*mul[y];
print(x2);
if(y>0)
{
putchar('.');
for(register ll i=1;iinline void printc(T x){putchar(x);}
templateinline void printc(T *x){while(*x)putchar(*x++);}
templateinline void prints(T x){for(register ll i=0;x[i]!='\0';i++)putchar(x[i]);}
templateinline void print(T x,char c){print(x),putchar(c);}
templateinline void printd(T x,ll y,char c){printd(x,y),putchar(c);}
templateinline void printc(T x,T c){printc(x),putchar(c);}
templateinline void printc(T *x,T c){printc(x),putchar(c);}
templateinline void prints(T x,char c){prints(x),putchar(c);}
加强版
基于 \(fread\) , \(fwrite\) 的输入输出优化。需要注意的是,在使用此优化后,只有读到文件末尾才会停止输入,如果使用键盘输入数据,则需要手动添加 \(EOF\) (在 \(Windows\) 系统下, \(EOF\) 手动输入是按 \(Ctrl+z\) ;在 \(Ubuntu\) 系统下, \(EOF\) 手动输入是按 \(Ctrl+d\) )。
#define getchar gc
#define putchar pc
inline char gc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
static char buf[100000],*pp=buf;
templateinline void pc(T c)
{
if(pp-buf==100000)fwrite(buf,1,100000,stdout),pp=buf;
*pp++=c;
}
inline void fsh(){fwrite(buf,1,pp-buf,stdout);pp=buf;}
templateinline bool read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c)){if(c==EOF)return false;f^=c=='-',c=getchar();}
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
return true;
}
templateinline bool readd(T &x)
{
register ll X=0;register double y=1.0;register char c=getchar();register bool f=0;
while(!isdigit(c)){if(c==EOF)return false;f^=c=='-',c=getchar();}
while(isdigit(c))X=(X<<3)+(X<<1)+(c^48),c=getchar();
x=X;
if(c!='.')return true;
c=getchar();
while(isdigit(c))x+=(y/=10)*(c^48),c=getchar();
if(f)x=-x;
return true;
}
templateinline bool readc(T &x)
{
register char c=getchar();
while(c==' '||c=='\n'||c=='\r'||c=='\t')c=getchar();
if(c==EOF)return false;
x=c;
return true;
}
templateinline bool readc(T *x)
{
register char c=getchar();
while(c==' '||c=='\n'||c=='\r'||c=='\t')c=getchar();
if(c==EOF)return false;
while(c!=' '&&c!='\n'&&c!='\r'&&c!='\t'&&c!=EOF)*x++=c,c=getchar();
*x=0;
return true;
}
templateinline bool reads(T &x)
{
x="";register char c=getchar();
while(c==' '||c=='\n'||c=='\r'||c=='\t')c=getchar();
if(c==EOF)return false;
while(c!=' '&&c!='\n'&&c!='\r'&&c!='\t'&&c!=EOF)x+=c,c=getchar();
return true;
}
templateinline void print(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
templateinline void printd(T x,ll y)
{
static ll mul[]={1};
for(register ll i=1;i<=18;i++)
mul[i]=(mul[i-1]<<3)+(mul[i-1]<<1);
if(x<-1e-12)putchar('-'),x=-x;
x*=mul[y];
register ll x1=(ll)round(x),x2=x1/mul[y],x3=x1-x2*mul[y];
print(x2);
if(y>0)
{
putchar('.');
for(register ll i=1;iinline void printc(T x){putchar(x);}
templateinline void printc(T *x){while(*x)putchar(*x++);}
templateinline void prints(T x){for(register ll i=0;x[i]!='\0';i++)putchar(x[i]);}
templateinline void print(T x,char c){print(x),putchar(c);}
templateinline void printd(T x,ll y,char c){printd(x,y),putchar(c);}
templateinline void printc(T x,T c){printc(x),putchar(c);}
templateinline void printc(T *x,T c){printc(x),putchar(c);}
templateinline void prints(T x,char c){prints(x),putchar(c);}
int main()
{
return fsh(),0;
}