对比一下各种快读

文章通过对比不同的输入输出方法,如cin/cout、scanf/printf、自定义快读快输以及使用fread和mmap等,展示了如何优化代码以提升处理大量数据时的效率。其中,fread和mmap的优化能显著减少程序运行时间。
摘要由CSDN通过智能技术生成

放上一道用来测试快读效率的题:A+B Problem (IO)

题目描述

输入 4 ∗ 1 0 6 4*10^6 4106 个整数 a , b a,b a,b,输出它们的和

1. 直接用 cin、cout,毫无疑问,超时(>1s):
#include <bits/stdc++.h>
using namespace std;

signed main(){
	int m=(int)2e6;
	while(m--){
		int a,b;cin>>a>>b;
		cout<<a+b<<'\n';
	}
	return 0;
}
2. cin、cout 关闭同步/解除绑定(380ms):
#include <bits/stdc++.h>
using namespace std;

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int m=(int)2e6;
	while(m--){
		int a,b;cin>>a>>b;
		cout<<a+b<<'\n';
	}
	return 0;
}
3. scanf、printf (410ms):
#include <bits/stdc++.h>
using namespace std;

signed main(){
	int m=(int)2e6;
	while(m--){
		int a,b;scanf("%d%d",&a,&b);
		printf("%d\n",a+b);
	}
	return 0;
}
4. 普通快读、快输(215ms):
#include <cstdio>
using namespace std;

namespace IO{
    #define re register
    #define tpl template<typename T>
    #define tpa template<typename T,typename... Args>
    tpl inline void read(T &x){
        x=0;re bool ff=false;re char ch=getchar();
        while(ch<'0'||ch>'9'){ff|=(ch=='-');ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=ff?~x+1:x;
    }
    tpa inline void read(T& x,Args&... args){read(x);read(args...);}
    inline void readc(char &c){
        do{c=getchar();}while(!((c>='a'&&c<='z')||(c>='A'&&c<='Z')));
    }
    tpl inline void write(T x){
        static T st[45];T top=0;
        if(x<0)x=~x+1,putchar('-');
        do{st[top++]=x%10;}while(x/=10);
        while(top)putchar(st[--top]^48);
    }
    tpl inline void write(T x,const char c){write(x);putchar(c);}
    inline void writes(const char *c){while(*c)putchar(*c++);putchar('\n');}
}
using namespace IO;

signed main(){
    int m=(int)2e6;
    while(m--){
        int a,b;read(a,b);
        write(a+b,'\n');
    }
    return 0;
}
5. fread 优化快读、快输(scanf 风格)(120ms):
#include <cstdio>
using namespace std;

namespace IO{
    #define re register
    #define getchar() (p1==p2&&(p2=(p1=ibuf)+fread(ibuf,1,buf_size,stdin),p1==p2)?EOF:*p1++)
    #define putchar(x) ((p3==obuf+buf_size)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
    #define tpl template<typename T>
    #define tpa template<typename T,typename... Args>
    typedef long long ll;
    const ll buf_size=1<<21;
    char ibuf[buf_size],*p1=ibuf,*p2=ibuf;
    char obuf[buf_size],*p3=obuf;
    tpl inline void read(T &x){
        x=0;re bool ff=false;re char ch=getchar();
        while(ch<'0'||ch>'9'){ff|=(ch=='-');ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=ff?~x+1:x;
    }
    tpa inline void read(T& x,Args&... args){read(x);read(args...);}
    inline void readc(char &c){
        do{c=getchar();}while(!((c>='a'&&c<='z')||(c>='A'&&c<='Z')));
    }
    tpl inline void write(T x){
        static T st[45];T top=0;
        if(x<0)x=~x+1,putchar('-');
        do{st[top++]=x%10;}while(x/=10);
        while(top)putchar(st[--top]^48);
    }
    tpl inline void write(T x,const char c){write(x);putchar(c);}
    inline void writes(const char *c){while(*c)putchar(*c++);putchar('\n');}
}
using namespace IO;

signed main(){
    int m=(int)2e6;
    while(m--){
        int a,b;read(a,b);
        write(a+b,'\n');
    }
    fwrite(obuf,1,p3-obuf,stdout);
    return 0;
}
6. fread 优化快读、快输(cin 风格)(96ms):
#include <bits/stdc++.h>
using namespace std;

namespace SOL {
#ifdef LOCAL
	FILE*Fin(fopen("test.in","r")),*Fout(fopen("test.out","w"));
#else
	FILE*Fin(stdin),*Fout(stdout);
#endif
namespace IO {
class qistream {
		static const size_t SIZE=1<<16,BLOCK=32;
		FILE*fp;
		char buf[SIZE];
		int p;
	public:
		qistream(FILE*_fp=stdin):fp(_fp),p(0) {
			fread(buf+p,1,SIZE-p,fp);
		} void flush() {
			memmove(buf,buf+p,SIZE-p),fread(buf+SIZE-p,1,p,fp),p=0;
		} template<class T>qistream&operator>>(T&x) {
			x=0;
			p+BLOCK>=SIZE?flush():void();
			bool flag=false;
			for(; !isdigit(buf[p]); ++p)flag=buf[p]=='-';
			for(; isdigit(buf[p]); ++p)x=x*10+buf[p]-'0';
			x=flag?-x:x;
			return*this;
		} char getch() {
			return buf[p++];
		} qistream&operator>>(char*str) {
			char ch=getch();
			while(ch<=' ')ch=getch();
			for(int i=0; ch>' '; ++i,ch=getch())str[i]=ch;
			return*this;
		}
} qcin(Fin);
class qostream {
		static const size_t SIZE=1<<16,BLOCK=32;
		FILE*fp;
		char buf[SIZE];
		int p;
	public:
		qostream(FILE*_fp=stdout):fp(_fp),p(0) {}~qostream() {
			fwrite(buf,1,p,fp);
		} void flush() {
			fwrite(buf,1,p,fp),p=0;
		} template<class T>qostream&operator<<(T x) {
			int len=0;
			p+BLOCK>=SIZE?flush():void();
			x<0?(x=-x,buf[p++]='-'):0;
			do buf[p+len]=x%10+'0',x/=10,++len;
			while(x);
			for(int i=0,j=len-1; i<j; ++i,--j)swap(buf[p+i],buf[p+j]);
			p+=len;
			return*this;
		} void putch(char ch) {
			buf[p++]=ch;
		} qostream&operator<<(const char*str) {
			for(int i=0; str[i]; ++i)putch(str[i]);
			return*this;
		}
} qcout(Fout);
} using namespace IO;
} using namespace SOL;

signed main() {
	int m=(int)2e6;
	while(m--) {
		int a,b;
		qcin>>a>>b;
		(qcout<<a+b).putch('\n');
	}
	return 0;
}
6. mmap 优化快读 + fread 优化快输(110ms):

mmap 需要加 #include <sys/mman.h> 头文件,考 CSP 时不能用!!!

#include <bits/stdc++.h>
#include <sys/mman.h>
using namespace std;

namespace IO{
    #define putchar(x) ((p3==obuf+buf_size)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
    #define tpl template<typename T>
    #define tpa template<typename T,typename... Args>
    const char*mbuf=(char*)mmap(nullptr,1<<28,PROT_READ,MAP_PRIVATE,fileno(stdin),0);
	typedef long long ll;
    const ll buf_size=1<<21;
    char obuf[buf_size],*p3=obuf;
	tpl inline void read(T& x){
		x=0;T f=1;
		while(*mbuf<'0'||*mbuf>'9'){if(*mbuf=='-')f=-1;mbuf++;}
		while(*mbuf>='0'&&*mbuf<='9')x=x*10+*mbuf++-'0'; x*=f;
	}
    tpa inline void read(T& x,Args&... args){read(x);read(args...);}
    inline void readc(char &c){
        do{c=getchar();}while(!((c>='a'&&c<='z')||(c>='A'&&c<='Z')));
    }
    tpl inline void write(T x){
        static T st[45];T top=0;
        if(x<0)x=~x+1,putchar('-');
        do{st[top++]=x%10;}while(x/=10);
        while(top)putchar(st[--top]^48);
    }
    tpl inline void write(T x,const char c){write(x);putchar(c);}
    inline void writes(const char *c){while(*c)putchar(*c++);putchar('\n');}
}
using namespace IO;

signed main(){
    int m=(int)2e6;
    while(m--){
        int a,b;read(a,b);
        write(a+b,'\n');
    }
    fwrite(obuf,1,p3-obuf,stdout);
    return 0;
}
补充:
  • 在 Linux 中可以用 getchar_unlocked() 来代替 getchar(),或者像下面这样(不过差别不大):
#define getchar() stdin->_IO_read_ptr<stdin->_IO_read_end?*stdin->_IO_read_ptr++:__uflow(stdin)
#define putchar(x) stdout->_IO_write_ptr<stdout->_IO_write_end?*stdout->_IO_write_ptr++=x:__overflow(stdout,x)
  • CF不支持 #include <sys/mman.h> 头文件,所以用不了 mmap
  • 读写文件时如果把 cin、cout 关闭同步/解除绑定了,一定要在最后刷新缓冲区(cout<<endl;)

至于为什么没有 mmap 实现快输,是因为我太蒻力(悲),如果有哪位大佬会请撅我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值