文章目录
在算法竞赛中,读入速度和输出速度一直是卡常的重要手段。也有不少人经历过被题目卡 cin 的情况。今天我给大家介绍一下算法竞赛中常用的读写方法及其优化。
声明:大部分情况下,只用读入优化就行。对于输出量大的题目再考虑使用输出优化。
一、scanf/printf
这两个函数来源于传统的 C,在 <stdio.h> 和 <cstdio>(仅 C++)中。使用方法:scanf("%占位符",&var); printf("%占位符\n",var);。这样比传统的 cin/cout 快,但由于书写复杂而很少被人采用。
scanf/printf 用法参考文章:详解c++中scanf和printf用法
二、cin/cout 优化
cin 和 cout是 C++ 的标准输入输出流,在 <iostream> 头文件中,使用方法也十分简单:cin>>var; cout<<var<<endl; 所以深受人们的喜爱。
在时间要求不高的题目中,用它们既省事,又可以让代码更美观。
缺点:cin/cout 在不加优化的情况下速度慢于 scanf 和 printf。
原因:C++ 为了和 C 保持同步、在混用 printf&scanf 和 cin&cout时的时候不发生混乱,将它的输入/输出流绑到了一起。
解决方案:可以手动关闭同步,从而提高 cin 和 cout 的效率。std::ios::sync_with_stdio(false); 同时,还可以通过std::cin.tie(nullptr); 来解除 cin 和 cout之间的绑定,进一步减轻 cin 的负担。
cin/cout 用法:C++ 基础的输入输出介绍:掌握cin与cout的奥秘
三、endl 优化
有一个被人忽略的“大杀手”:endl。这一个语句和 \n 的效果相同,但更方便书写,因此被人们广泛采用。其实它的速度也特别慢。可能会导致某些题目超时。
原因:endl 输出时会清空缓冲区,这是为了让用户能及时看到输出,但会拖慢速度。并且由于它本身的功能定义,很难进行优化。
解决方案:打不过就不用呗 对于输出量大且需要换行的题目,使用 endl 有超时的风险,建议使用 cout<<'\n'。(平常刷题也建议用 \n,比较保险)
在实测中,C++14 的版本下,cin/cout 优化 + endl 优化的速度已经远快于 scanf/printf,建议在新评测机上使用上面两种方法优化。
#include<iostream>
using namespace std;
int a[105];
int main(){
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cout<<"a["<<i<<"]="<<a[i]<<"\n";
}
return 0;
}
四、传统快读、快写
原理:单个字符的输入输出速度要比读入数字快,因此我们以字符的形式先读入,然后处理计算转为数字,再用字符输出。
关于 isdigit()
在判断某个字符是不是整数时用的 isdigit() 函数,在不同编译器上的速度不一样。
在 这篇文章 中的测试结果:自己写比 VS 中的 isdigit() 快,但比 g++ 中的 isdigit() 慢。而且 g++ 中的 isdigit() 比 VS 中的 isdigit() 更快。
这篇文章 给我们展示了 Linux 内核中该函数王者级别的实现,大家可以学习。
自己写的话:
#define my_isdigit(c) ( (c)>='0'&&(c)<='9' ) // C语言
inline bool my_isdigit(char c){
return (c>='0'&&c<='9'); } // C++
快读
原理是先用单个字符读入所有零散的数字,再拼起来。拼数和判断字符见 这篇文章。
template<typename T>
inline void read(T &x){
T w=1; x=0;
char c=getchar();
while(!isdigit(c)){
if(c=='-'){
w=-1;} c=getchar();}
while(isdigit(c)){
x=x*10+(c-'0'); c=getchar();}
x=x*w;
}
快写
原理是把原来完整的数字拆成一个个字符输出。用递归的常数会略大,可以用模拟栈的方法时限。
递归代码:
template<typename T>
inline void write(T x){
if(x<0){
putchar('-'); x=-x;}
if(x>=10){
write(x/10);}
write(x%10+'0'); //+'0'是为了让数字类型的x%10变成字符输出
}
模拟栈代码:(不能用模板了,要自己指定类型)
inline void write(int x){
static int st[35] = {
0}

最低0.47元/天 解锁文章
2490

被折叠的 条评论
为什么被折叠?



