📜  快速I O进行竞争性编程(1)

📅  最后修改于: 2023-12-03 15:39:35.519000             🧑  作者: Mango

快速 I/O 进行竞争性编程

竞争性编程(Competitive Programming)是指通过竞赛的方式来锻炼算法和编程能力。在竞争性编程中,时间是一项非常宝贵的资源。因此,如何快速地进行输入输出(I/O)操作对于解决问题至关重要。

本文将介绍如何使用快速 I/O 进行竞争性编程,以加快运行时间和避免超时等问题。

为什么需要快速 I/O

在竞争性编程中,算法的时间复杂度通常不是极高的,但是输入数据规模往往非常大。如果使用普通的 I/O 方法,例如 scanf 和 printf,读入或写出大量数据会非常耗时。

因此,需要使用更快的 I/O 方法来加快程序的运行速度,并防止时间超限。

快速输入

快速输入一般分为两类:基于 getchar 读入一整行,基于 fread 读入大量数据。

基于 getchar 读入一整行
inline int read() {
    int x = 0, flag = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') flag = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * flag;
}

该方法使用 getchar 读入一整行,并将其中的数字字符转换为数字。该方法的局限性在于,数字必须在一行中,否则只能读入第一个数字。

基于 fread 读入大量数据
const int BUF_SIZE = 1 << 20;
char buf[BUF_SIZE], *p1 = buf, *p2 = buf;
inline int gc() {
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, BUF_SIZE, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read() {
    int x = 0, flag = 1;
    char ch = gc();
    while (!isdigit(ch)) {
        if (ch == '-') flag = -1;
        ch = gc();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = gc();
    }
    return x * flag;
}

该方法使用 fread 读入大量数据,并使用 getchar 获取每个数字字符。如果 fread 读完了当前缓冲区的数据,则重新读入。

快速输出

快速输出一般分为两类:基于 putchar 输出到缓存区,基于 sprintf 直接输出到字符串中。

基于 putchar 输出到缓存区
const int N = 100000;
char obuf[N], *o = obuf;

inline void putc(const char &x) {
    *++o = x;
}

inline void flush() {
    fwrite(obuf + 1, sizeof(char), o - obuf, stdout);
    o = obuf;
}

inline void print(const int &x) {
    if (x < 0) putc('-'), print(-x);
    else {
        static int sta[21], top;
        while (sta[++top] = x % 10, x /= 10);
        while (top) putc(sta[top] ^ 48), --top;
    }
}

inline void print(const char &x) {
    putc(x);
}

inline void println() {
    putc('\n');
    flush();
}

inline void print(const char *s) {
    while (*s) putc(*s), ++s;
}

inline void print(const double &x) {
    static char buf[21];
    sprintf(buf, "%lf", x), print(buf);
}

该方法将输出的内容保存在 obuf 中,使用 putc 输出每个字符。如果 obuf 的大小达到一定值,就会使用 fwrite 一次性将所有字符输出。

基于 sprintf 直接输出到字符串中
inline void print(const int &x, char *s) {
    sprintf(s, "%d", x);
}

inline void print(const char *x, char *s) {
    sprintf(s, "%s", x);
}

inline void print(const double &x, char *s) {
    sprintf(s, "%lf", x);
}

该方法使用 sprintf 将输出内容直接输出到字符串中。该方法的优点是输出时无需判断当前指针位置,缺点是速度较慢。

总结

本文介绍了在竞争性编程中如何使用快速 I/O,以加快输入输出速度,提高程序运行速度。无论是基于 getchar 还是 fread 读入数据,都需要仔细处理数字字符的转换;无论是基于 putchar 还是 sprintf 输出数据,都需要控制输出内容和指针位置。希望这些方法能够帮助程序员在竞赛中更快地解决问题。