📜  用于竞争性编程的快速 I/O

📅  最后修改于: 2021-10-22 03:43:07             🧑  作者: Mango

在竞争性编程中,尽可能快地读取输入非常重要,这样我们才能节省宝贵的时间。

您一定看过各种问题陈述:“警告: I/O 数据大,使用某些语言时要小心(尽管如果算法设计良好,大多数应该没问题)” 。解决此类问题的关键是使用 Faster I/O 技术。

通常建议使用 scanf/printf 而不是 cin/cout 来实现快速输入和输出。但是,您仍然可以使用 cin/cout 并通过在 main()函数包含以下两行来实现与 scanf/printf 相同的速度:

ios_base::sync_with_stdio(false);

如果在程序执行其第一次输入或输出操作之前调用它,它将打开或关闭所有 C++ 标准流与其对应的标准 C 流的同步。添加 ios_base::sync_with_stdio (false); (默认情况下为 true)在任何 I/O 操作避免此同步之前。它是 std::ios_base函数的静态成员。

cin.tie(NULL);

tie() 是一种简单地保证在 std::cin 接受输入之前刷新 std::cout 的方法。这对于需要控制台不断更新但也会减慢大型 I/O 程序的交互式控制台程序很有用。 NULL 部分只返回一个 NULL 指针。

此外,您可以使用单个包含来包含标准模板库 (STL):

#include 

因此,您的竞争性编程模板可能如下所示:

#include 
using namespace std;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    return 0;
}

推荐使用 cout << “\n”;而不是 cout << endl;。 endl 较慢,因为它强制刷新流,这通常是不必要的(有关详细信息,请参阅此)。 (如果您正在编写交互式进度条,则需要刷新,但在编写一百万行数据时则不需要刷新。)写入 ‘\n 而不是 endl。

我们可以在问题 INTEST – Enormous Input Teston SPOJ 上测试我们的输入和输出方法。在进一步阅读之前,我建议您先解决问题。

C++ 4.9.2 中的解决方案

普通 I/O :下面的代码使用 cin 和 cout。该解决方案以 2.17 秒的运行时间被接受。

// A normal IO example code
#include 
using namespace std;
int main()
{
    int n, k, t;
    int cnt = 0;
    cin >> n >> k;
    for (int i=0; i> t;
        if (t % k == 0)
            cnt++;
    }
    cout << cnt << "\n";
    return 0;
}

快速 I/O但是,我们可以通过添加两行来做得更好并大大减少运行时间。下面的程序以 0.41 秒的运行时间被接受。

// A fast IO program
#include 
using namespace std;
  
int main()
{
    // added the two lines below
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);   
      
    int n, k, t;
    int cnt = 0;
    cin >> n >> k;
    for (int i=0; i> t;
        if (t % k == 0)
            cnt++;
    }
    cout << cnt << "\n";
    return 0;
}

现在,说到 ACM ICPC、Google CodeJam、TopCoder Open 等竞争性比赛,这里有一个以最快方式读取整数的独家代码。

void fastscan(int &number)
{
    //variable to indicate sign of input number
    bool negative = false;
    register int c;
  
    number = 0;
  
    // extract current character from buffer
    c = getchar();
    if (c=='-')
    {
        // number is negative
        negative = true;
  
        // extract the next character from the buffer
        c = getchar();
    }
  
    // Keep on extracting characters if they are integers
    // i.e ASCII Value lies from '0'(48) to '9' (57)
    for (; (c>47 && c<58); c=getchar())
        number = number *10 + c - 48;
  
    // if scanned input has a negative sign, negate the
    // value of the input number
    if (negative)
        number *= -1;
}
  
// Function Call
int main()
{
    int number;
    fastscan(number);
    cout << number << "\n";
    return 0;
}