康老师艾滋病康复网,内容丰富有趣,生活中的好帮手!
康老师艾滋病康复网 > C++整数快速读写模板(快速读入+快速写)详解

C++整数快速读写模板(快速读入+快速写)详解

时间:2019-01-27 04:29:29

相关推荐

众所周知,C++的cin和cout速度很慢,在OJ上会耽误大量的时间

因此一般使用cin,cout时 会在main的第一行加上一句:

iostream::sync_with_stdio(false);

这句话会解除cin,cout和stdio之间的同步锁这样cin和cout的速度会有明显的改善

和scanf和printf不相上下 有时候甚至比后两者更快一些

但是注意执行完上述语句后只能使用{cin,cout}和{printf,scanf,putchar,getchar}的一边

如果两个集合里的函数混用 会导致输出顺序混乱(前面的和后面的字符穿插在一起乱七八糟)

我一般习惯解除同步锁之后直接用cin,cout

选择上面的方法或者直接采用scanf printf 基本上可以应付绝大多数问题 但如果一道题目的数据量特别大

(比如T<10000000组输入数据 每组若干个数的时候) 以上方法也有些力不从心

这时就需要用到快速读入模板

这个模板的原理之一是用较快的getchar代替scanf或者cin 使速度有一个较大的提升

而一个一个字符地getchar显然效率上有些低 所以更好的方法是用fread把数据读入缓冲区(一次数万个字符)再处理

这样几乎是最快的方法了

网上有一个很流行的快读模板(因为到处都是实在找不到发布源了)是这样的:

这个也是我们学校学长推荐的快读模板

namespace fastIO {#define BUF_SIZE 100000//fread -> readbool IOerror = 0;inline char nc() {static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;if(p1 == pend) {p1 = buf;pend = buf + fread(buf, 1, BUF_SIZE, stdin);if(pend == p1) {IOerror = 1;return -1;}}return *p1++;}inline bool blank(char ch) {return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';}inline void read(int &x) {char ch;while(blank(ch = nc()));if(IOerror)return;for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');}inline void readll(long long int &x) {char ch;while(blank(ch = nc()));if(IOerror)return;for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');}#undef BUF_SIZE};

上面模板的效率确实很高 但是个人认为用函数来写读入很麻烦

比如输入三个整数a b c 必须要写read(a);read(b);read(c);才行 而且上述模板不支持输入负数也很麻烦

于是我做了一些修改 所有的读入函数使用重载运算符>>的方式实现

而且不限制读入的数据类型(如果不是可以加速的整数类型会自动转给cin读入)

并且增加了一个快速写模板 把整数的输出任务用putchar执行 也提高了输出的速度

修改后的模板如下:(main函数中是测试代码)

#include <bits/stdc++.h>using namespace std;// *Copyright by i.Pear Works*//本IO模块的用途是方便地读写大量整数//若题目整数不多 请改用关闭同步锁的cin(因为本模块不支持关闭同步锁)或scanfnamespace FastIO{//不支持while(qin>>x)的多组数据输入方法//任何情况下请不要关闭sync_with_stdio同步锁!!//如果您选择关闭同步锁以获得更高的cin/cout速度 使用此模块会导致不可预期的后果//此处为负数读取功能开关//若程序不会读入负数 请去除下方注释符号 以获得30%的输入提速//#define DisableNegative true//此处为兼容性模式开关 若程序IO存在 *任何* *int/ll/char[]/string/char(包括空格回车)* 之外的类型//请去除下方注释符号 降低一半的速度以获得兼容性//#define EnableCompatibility trueclass Scanner{char cht;bool ifNegative;char stringBuf[10000];#ifndef EnableCompatibility#define BUF_SIZE 524288char nc(){static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;if(p1==pend){p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);if(pend==p1)return ' ';}#ifndef DisableNegativeif(*p1=='-'){ifNegative=true;p1++;return nc();}#endifreturn *p1++;}#elseinline char nc(){return getchar();}#endifinline bool blank(char ch){return ch=='\r'||ch=='\n'||ch==' '||ch=='\t';}public:Scanner operator>>(int&x){#ifndef DisableNegativeifNegative=false;#endifwhile(blank(cht=nc()));for(x=cht-'0';(cht=nc())>='0'&&cht<='9';x=x*10+cht-'0');#ifndef DisableNegativeif(ifNegative)x*=-1;#endifreturn *this;}Scanner operator>>(long long int&x){#ifndef DisableNegativeifNegative=false;#endifwhile(blank(cht=nc()));for(x=cht-'0';(cht=nc())>='0'&&cht<='9';x=x*10+cht-'0');#ifndef DisableNegativeif(ifNegative)x*=-1;#endifreturn *this;}Scanner operator>>(string&str){int p=0;while(blank(cht=nc()));for(stringBuf[p++]=cht;!blank(cht=nc());stringBuf[p++]=cht);stringBuf[p]='\0';str=stringBuf;return *this;}Scanner operator>>(char str[]){int p=0;while(blank(cht=nc()));for(str[p++]=cht;!blank(cht=nc());str[p++]=cht);str[p]='\0';return *this;}template<typename F>inline Scanner operator>>(F&f){cin>>f;return *this;}};class Printer{int num;char chr[21];public:Printer operator<<(int x){if(x==0){putchar('0');return *this;}if(x<0)x*=-1,putchar('-');num=0;while(x) chr[++num]=(x%10)+48,x/=10;while(num) putchar(chr[num--]);return *this;}Printer operator<<(long long int x){if(x==0){putchar('0');return *this;}if(x<0)x*=-1,putchar('-');num=0;while(x) chr[++num]=(x%10)+48,x/=10;while(num) putchar(chr[num--]);return *this;}inline Printer operator<<(char x){putchar(x);return *this;}Printer operator<<(const char str[]){int p=0;while(str[p]!='\0'){putchar(str[p++]);}return *this;}inline Printer operator<<(string&x){for(string::iterator i=x.begin();i<x.end();i++)putchar(*i);return *this;}template<typename F>inline Printer operator<<(F&f){cout<<f;return *this;}};Scanner qin;Printer qout;#define endl '\n'}using namespace FastIO;//-----------------模板到此结束 以下是测试代码--------------------int main(){//testfreopen("D:\\1.txt","r",stdin);long long int arr[10];for(int i=1;i<10;i++){qin>>arr[i];}for(int i=1;i<10;i++){qout<<arr[i]<<endl;}}int main2(){// !!run this test with "EnableCompatibility" mode onfreopen("D:\\1.txt","r",stdin);long long int a;long long int b;int c;double d;string e;float f;qin>>a>>b>>c>>d>>e>>f;qout<<a<<" "<<b<<endl<<c<<" "<<d<<endl<<e<<" "<<f;}

上面的“兼容性模式”是不再建立缓冲区而用疯狂getchar替代 这样不会把后面不是整数的数据也存进缓冲区

实验证明这样速度会慢一半 但是也比scanf快得多

如果不需要读取负数 可以打开上面DisableNegative的开关 编译时会少几个判断 效率也有一些提升

在不开启兼容性+DisableNegative的模式下 和原模板的速度没有区别

简述一下用法:只要把这段代码粘贴到您代码的最上方 然后使用qin,qout(q是quick的意思)代替cin,cout就可以了

所有的输入输出都使用运算符<<,>>来进行

经过测速 虽然用了大量的反复重载和类 速度并未改变 但从使用上来说也许会更方便一些

已知的一些问题:

1.qout不能正确的输出-9223372036854775808这个数(ll的最小值)因为去掉符号会溢出

但只有这一个数不能用 实际需要输出这个数的场合也不多见 就不为了它降低整体效率了

2.快速写部分对于绝大多数类型都有加速作用 但是快读只对整数类型起作用

如果数据中不是含有大量的整数 请慎用此模板(因为与sync_with_stdio不共存)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。