读入读出优化

TJDXT

先放代码之后再说原理,如果实在不想知道原理,就直接背过,但是建议看一下下面的注意事项和后面的前几个原理。

代码实现

#include <bits/stdc++.h> using namespace std; #define ll long long #define rl register ll #define fom(i, a) for(int i=a; i; -- i) #define foa(i, a, b) for(int i=a; i < b; ++ i) #define fos(i, a, b) for(int i=a; i <= b; ++ i) #define fop(i, a, b) for(int i=a; i >= b; -- i) // 这一部分不是必要,这个是我自己的个人习惯 namespace IO { int pp1=-1; const int pp2=(1<<21)-1; char buf[1<<21],*p1=buf,*p2=buf,buffer[1<<21]; inline void flush() {fwrite(buffer,1,pp1+1,stdout); pp1=-1;} inline void pc(const char ch) {if(pp1==pp2) flush(); buffer[++pp1]=ch;} inline char gc(){ return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} template <class T> inline void read(T &res){char ch=gc();bool f=0;res=0; for(;!isdigit(ch);ch=gc()) f|=ch=='-'; for(;isdigit(ch);ch=gc()) res=(res<<1)+(res<<3)+(ch^48); res=f?~res+1:res;} template <class T> inline void ww(T x) { if(!x) pc('0'); else { static int stk[21]; int top = 0; if(x<0) pc('-'),x=~x+1; while(x) stk[top++]=x%10, x/=10; while(top--) pc(stk[top]^48);}} } #define ws IO::pc(' ') #define wl IO::pc('\n') #define ww(x) IO::ww(x) #define read(x) IO::read(x) #define flush() IO::flush() int main() { // balabala... flush(); return 0; }

注意事项

当你使用了这个快读快写之后你应该要注意,不能够将 cin, scanf 和 read 相互之间混用,因为会导致缓冲区紊乱。同时cout, printf 和 ww 也是不能混用的,原因同上。如果非要混用输出,那么就每一段之后进行一次 flush 操作。

eg:

ww(x), wl, flush(); // 这个flush很重要!!不然你会看见一堆很乱的输出,不知所云 cout << "asd" << endl; printf("move disk %d from %c to %c\n", n, a, c);

还有一点就是我们如果使用了read 我们只能用 freopen 来读入文件。

原理

我们用 buf 来枚举读入的缓冲区,用 buffer 来模拟输出的缓冲区,然后每个缓冲区域两个指针。

我们的 flush 就是将目前缓冲区里面的一口气全吐出去。

然后我们的 gc 是用来模拟 getchar 也是先不断读入,然后如果读到缓冲区已经达到极限。就一口气吐出去。

然后快读快写就是很板的东西了。isdigit 是可以判断这个是不是数字,我们首先要处理数字前面的符号,换行空格啥的。但是我们有用的只有符号,所以就一个位运算搞定结果。然后我们就读入后面的数字,也是位运算,读者自行理解不难。

后面的快写为了减小常数,就可以写成一个栈的形式,读者自理解平凡。

write at the back

其实如果你实在搞不懂上面的,你可以换成下面的板子。这个板子没有什么限制,就是在读入极多数字(1e9 个 18 位数字)的时候会比上面慢上一点。

但是用来吊打 cin cout printf scanf 没有什么问题。

#include <bits/stdc++.h> using namespace std; #define ll long long #define rl register ll template <class T> inline void read(T &res) { char ch = getchar(); bool f = 0; res = 0; for(; !isdigit(ch); ch = getchar()) f |= ch == '-'; for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48); res = f ? ~res + 1 : res; } template <class T> inline void waw(T x) { if(x > 9) waw(x / 10); putchar(x % 10 ^ 48); } template <class T> inline void ww(T x) { if(x < 0) x = ~x + 1, putchar('-'); waw(x); } // 这里的输出你也可以自己写个栈,但是懒鱼我觉得这么写简单以前(

上面的代码是懒鱼我直接在 cnblog 上面打的,如果在使用的时候发现有 bug,请联系懒鱼改过来。

祝大家年能够快乐的卡常 A 题。


__EOF__

本文作者carp
本文链接https://www.cnblogs.com/carp-oier/p/fastIO.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   carp_oier  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示