PrevNext

USACO 说明页面简要介绍了几种加速输入输出的方法:

对于一些输入规模较大的高难度题目,参赛者可以使用快速输入输出,以便更容易在时限内通过。C++ 用户如果使用 cin/cout,可以在 main 函数开头添加 “ios_base::sync_with_stdio(false); cin.tie(0);”;Java 用户可以使用 BufferedReader 代替 Scanner。

这些做法有什么作用,实际差别又有多大?我们将使用下面的任务测试输入输出速度:

示例任务

输入包含两个整数 MM0M10\le M\le 1)和 NN1N1061\le N\le 10^6),随后是一个由 NN 个非负整数组成的序列,每个数都小于 109+710^9+7

  • 如果 M=0M=0,输出输入序列之和对 109+710^9+7 取模的结果。
  • 如果 M=1M=1,依次输出输入序列每个前缀之和对 109+710^9+7 取模的结果。

样例输入 1:

1 6
1
2
3
4
5
1000000000

样例输出 1:

1
3
6
10
15
8

样例输入 2:

0 6
1
2
3
4
5
1000000000

样例输出 2:

8

随机生成测试数据后,输入和输出文件都会达到约 10 MB。实际比赛中可能出现这么大的输入文件(Robotic Cow Herd 的第 11 个输入文件约为 10.3 MB),但输出文件通常不会这么大(我们所知最大的来自 Minimum Cost Paths,约为 2.8 MB)。

Focus Problem – try your best to solve this problem before continuing!

标准输入输出

较慢

一些简单的输入输出方法远远无法在时限内运行完毕:

input + print (18.9s)

较快

sys.stdin.readline 代替 input 可以获得大幅加速。

readline + print (2.9s)

同时使用 sys.stdin.readlinesys.stdout.write 会稍快一些:

readline + write (2.4s)

文件输入输出

与标准输入输出非常相似。

readline + write (2.4s)

C++

补充说明

Resources
CF

测量各种输入输出方法的耗时

ios::sync_with_stdio(false)

引自第二份资料:

这会禁用 C 与 C++ 标准流之间的同步。默认情况下,所有标准流都是同步的,因此实际使用时可以混合 C 和 C++ 风格的输入输出,并获得合理且符合预期的结果。禁用同步后,C++ 流可以拥有各自独立的缓冲区,此时混用两种风格的输入输出就可能产生难以预料的结果。

cin.tie(nullptr)

引自第二份资料:

这会解除 cincout 的绑定。两个流绑定时,每当其中一个流执行输入输出操作前,另一个流都会自动刷新。

默认情况下,cincout 绑定,以确保合理的用户交互。例如:

std::cout << "Enter name:";
std::cin >> name;

如果 cincout 绑定,程序提示用户输入前会先刷新输出,也就是确保提示内容已显示在控制台上。如果解除绑定,程序可能已经阻塞并等待用户输入姓名,但“Enter name”消息尚未显示,因为 cout 默认带缓冲,只有在需要时或缓冲区已满时才会刷新并显示输出。

因此,如果解除 cincout 的绑定,那么每次希望在等待 cin 输入前显示内容时,都必须手动刷新 cout

Warning: cout.tie(nullptr)

你可能会看到一些竞赛程序员加入这一行。实际上它没有任何作用,因为 cout 本来就没有与其他流绑定。详情请参阅这篇帖子

Java

Python

题目

StatusSourceProblem NameDifficultyTags
CFMedium

Module Progress:

PrevNext