c++算法竞赛输入输出优化

在 C++ 算法竞赛中,输入输出的速度往往是影响程序性能的关键因素
其实主要是用来优化暴力代码的啦o(///▽///)q

下面我将给出几组常用输入输出板子

Part-1. 标准输入输出

大家对这个应该很熟悉了吧?想必最开始接触 OI的时候大家写的输入输出就是用的这个吧。

#include <iostream>
using namespace std;

int main() {
    int a;
    cin >> a;          // 输入
    cout << a << endl; // 输出
    return 0;
}

其实你做多了题目就会发现这个cin和cout是非常慢的,因为它从缓冲区中读入数据,而这个缓冲常常是同步的,因为它还需要辨别输入类型。
为了加速这东西,所以我们可以在代码中加入这样几句话,意为关闭同步流:

ios::sync_with_stdio(false); // 解除cin与stdin的绑定
cin.tie(0);                  // 解除cin与cout的绑定
cout.tie(0);                 // 解除cout与cin的绑定

但是在大量的数据面前,它的表现仍然不够出色,常常有TLE的存在。
所以就有了下面这个东西

Part-2.\(scanf\) and \(printf\)

scanf/printf 是大多数有经验的 OIer 常用的输入输出方式。
由于需要加上格式符,它不太受广大初学者喜欢。
但请注意:它很快!
不过它也有一个缺点,相信很多做过字符串题目的 OIer 都清楚 ——scanf 可能会读入换行符!
这里解释下原因:
Linux 和 Windows 下的换行符是不一样的!
至于具体哪里不一样,读者可以查阅网上资料,这里只做原因解释。因此,如果要读入字符且涉及换行等情况,建议先读一句:

scanf ("\n");

这样基本就没什么问题了 QAQ。

等等,你不是说它很快吗?为什么我在处理超过 100w 数据时,会因为它而 TLE 呢?
因为它还不够快!

Part-3. 手写快读快写

利用getchar()和putchar()函数实现,速度比标准 IO 快很多:
不过相对于上面两种来说会难写的多,不过提升也是相对而言比较可观的

#include <cstdio>
#include <cstring>

// 快读
inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x * f;
}

// 快写
inline void write(int x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

// 快写带换行
inline void writeln(int x) {
    write(x);
    putchar('\n');
}

Part-4. 手写\(Super快读\) and \(Super快写\)

进一步优化,利用缓冲区批量读取和写入,速度超级快,适合处理超大量数据
不过这个难写程度嘛。。。。。。
还是自己体会一下吧。

#include <cstdio>
#include <cstring>

// 超级快读
namespace fastIO {
    const int BUF_SIZE = 1 << 20;
    char buf[BUF_SIZE], *p1, *p2;
    
    // 获取一个字符
    inline char gc() {
        if (p1 == p2) {
            p1 = buf;
            p2 = buf + fread(buf, 1, BUF_SIZE, stdin);
        }
        return p1 == p2 ? EOF : *p1++;
    }
    
    // 读取整数
    inline int read() {
        int x = 0, f = 1;
        char ch = gc();
        while (ch < '0' || ch > '9') {
            if (ch == '-') f = -1;
            ch = gc();
        }
        while (ch >= '0' && ch <= '9') {
            x = x * 10 + (ch - '0');
            ch = gc();
        }
        return x * f;
    }
    
    // 读取长整数
    inline long long readll() {
        long long x = 0, f = 1;
        char ch = gc();
        while (ch < '0' || ch > '9') {
            if (ch == '-') f = -1;
            ch = gc();
        }
        while (ch >= '0' && ch <= '9') {
            x = x * 10 + (ch - '0');
            ch = gc();
        }
        return x * f;
    }
}

// 超级快写
namespace fastIO {
    char obuf[BUF_SIZE], *pO = obuf;
    
    // 刷新缓冲区
    inline void flush() {
        fwrite(obuf, 1, pO - obuf, stdout);
        pO = obuf;
    }
    
    // 写入一个字符
    inline void pc(char c) {
        if (pO - obuf == BUF_SIZE) flush();
        *pO++ = c;
    }
    
    // 写入整数
    inline void write(int x) {
        if (x < 0) {
            pc('-');
            x = -x;
        }
        if (x > 9) write(x / 10);
        pc(x % 10 + '0');
    }
    
    // 写入长整数
    inline void writell(long long x) {
        if (x < 0) {
            pc('-');
            x = -x;
        }
        if (x > 9) writell(x / 10);
        pc(x % 10 + '0');
    }
    
    // 写入字符串
    inline void write(const char *s) {
        while (*s) pc(*s++);
    }
    
    // 写入换行
    inline void writeln() {
        pc('\n');
    }
}

// 程序结束时自动刷新缓冲区
struct FastIOInitializer {
    ~FastIOInitializer() {
        fastIO::flush();
    }
} fastIOInitializer;

使用说明

标准 IO 适合简单题目,但数据量大时会超时
快读快写适用于大多数算法竞赛题目,速度足够快
超级快读超级快写适用于数据量极大的场景(如 1e6 级别以上数据)
使用时只需将对应的函数包含在代码中,然后直接调用即可啦:

int main() {
    int a = fastIO::read();         // 超级快读
    long long b = fastIO::readll(); // 读取长整数
    fastIO::write(a);               // 超级快写
    fastIO::writeln();              // 换行
    return 0;
}

这些输入输出方法可以根据题目的数据规模灵活选择,在保证正确性的前提下最大化程序运行效率。
妈妈再也不用担心我暴力拿不了高分啦ヾ (*)

posted @ 2025-08-11 15:55  Rookie青果  阅读(83)  评论(0)    收藏  举报