NOIP比赛中如何加速c++的输入输出

在竞赛中,遇到大数据时,往往需要更快的读取方式。由于比赛中输出一般规模较小,本文只讨论输入如何加速.

现在我们生成1000000个随机数,构成1000*1000的矩阵,然后输入比较时间(Win 10系统)

#include<iostream>
#include<stdlib.h>
#include<ctime>
using namespace std;
int main(){
srand((unsigned)time(NULL));
freopen("out1.txt","w",stdout);
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
cout<<rand()<<' ';
}
cout<<endl;
}
}

cin的速度

在比赛中,经常出现数据集超大造成 cin TLE的情况。这时候大部分人(包括原来我也是)认为这是cin的效率不及scanf的错

准确的说,cin在不优化的情况下效率是很低的,我们来测试一下

#include<iostream>
#include<cstdio>
#include<ctime>
using namespace std;
int a[1005][1005];
int main(){
freopen("out1.txt","r",stdin);
double s=clock();
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
cin>>a[i][j];
}
}
printf("time used=%.3fs\n",double(clock()-s)/CLOCKS_PER_SEC);
}



可以看出,cin的用时达到了惊人的0.763s!!!假如运行时间限制为1s,那么程序只剩下0.3秒来计算,是极容易TLE的

因此,遇到大数据时尽量避免用cin

有博客提到:

默认的时候,cin与stdin总是保持同步的,也就是说这两种方法可以混用,而不必担心文件指针混乱,同时cout和stdout也一样,两者混用不会输出顺序错乱。正因为这个兼容性的特性,导致cin有许多额外的开销,如何禁用这个特性呢?只需一个语句std::ios::sync_with_stdio(false);,这样就可以取消cin与stdin的同步了

其实还有一个等价的写法

cin.tie(0);//取消cin的同步
cout.tie(0);//取消cout的同步

我们来验证一下:

#include<iostream>
#include<cstdio>
#include<ctime>
using namespace std;
int a[1005][1005];
int main(){
freopen("out1.txt","r",stdin);
std::ios::sync_with_stdio(false);//优化
double s=clock();
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
cin>>a[i][j];
}
}
printf("time used=%.3fs\n",double(clock()-s)/CLOCKS_PER_SEC);
}



时间变成了0.173s,相比cin是飞跃性的优化

但是别急着高兴,本人亲测,在NOIP的评测机上这样子会爆0

因此,noip比赛中坚决不要写std::ios::sync_with_stdio(false)

爆0的原因如下

noip明确要求使用freopen,而freopen是stdio库中的,既然我们已经取消了iostream和stdio的同步,这样会造成文件指针混乱,进而导致RE

scanf的速度

既然noip比赛中坚决不要写std::ios::sync_with_stdio(false),那么我们可以用scanf

#include<iostream>
#include<cstdio>
#include<ctime>
using namespace std;
int a[1005][1005];
int main(){
freopen("out1.txt","r",stdin);
double s=clock();
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
scanf("%d",&a[i][j]);
}
}
printf("time used=%.3fs\n",double(clock()-s)/CLOCKS_PER_SEC);
}



时间变成了0.641s,相比无优化的cin还是较快的

手写快速读入的速度

我们知道,getchar的速度是很快的,但它只能读取单个字符,因此,我们通过将字符转为整型来优化,同理可以转成long long

快速读入的代码NOIP初赛曾经考过

#include<iostream>
#include<cstdio>
#include<ctime>
using namespace std;
int a[1005][1005];
inline int read(){//非常重要的快速读入代码
int x=0,sign=1;
char c=getchar();
while(c>'9'||c<'0'){//判断符号
if(c=='-') sign=-1;
c=getchar();
}
while(c>='0'&&c<='9'){//转换数
x=x*10+c-'0';
c=getchar();
}
return x*sign;
}
int main(){
freopen("out1.txt","r",stdin);
double s=clock();
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
a[i][j]=read();
}
}
printf("time used=%.3fs\n",double(clock()-s)/CLOCKS_PER_SEC);
}

运行后的结果如下:



现在这个方法只需0.163s,比其他的方法都快,而且不会在评测机上出现问题,并且也没有调用许多函数

遇到数据量大的题,尽量用手写的快速读入来读取

总结

  1. 遇到大数据时尽量避免用cin
  2. noip比赛中坚决不要写std::ios::sync_with_stdio(false)来优化cin
  3. 如果是double或输入格式较复杂用scanf
  4. 遇到数据量大的题,且是long long或int,尽量用手写的快速读入来读取

NOIP比赛中如何加速c++的输入输出的更多相关文章

  1. [ACM训练] ACM中巧用文件的输入输出来改写acm程序的输入输出 + ACM中八大输入输出格式

    ACM中巧用文件的输入输出来改写acm程序的输入输出 经常有见大神们使用文件来代替ACM程序中的IO,尤其是当程序IO比较复杂时,可以使自己能够更专注于代码的测试,而不是怎样敲输入. C/C++代码中 ...

  2. 新手数据比赛中数据处理方法小结(python)

    第一次参加,天池大数据竞赛(血糖预测),初赛排名1%.因为自己对python不熟悉,所以记录一下在比赛中用到的一些python方法的使用(比较基础细节,大佬绕道): 1.数据初探 data.info( ...

  3. 【CTF 攻略】CTF比赛中关于zip的总结

    [CTF 攻略]CTF比赛中关于zip的总结   分享到: --> 本文首发于安全客,建议到原地址阅读,地址:http://bobao.360.cn/ctf/detail/203.html 前言 ...

  4. java:比赛中常用方法整理——字符串(基础)

    一.将字符串转化为字符数组: toCharArray返回一个字符数组. char[] a=J.toCharArray(); 二.字符串的长度 字符串的长度和字符数组的长度是不一'样'的. 字符串长度( ...

  5. java:编程比赛中有用的方法整理(一)数组

    我曾经参加过几次编程比赛,但是当时用的是c语言,现在学习了java,打算专攻java组,故以此整理. 数组无论在哪里都必不可少. 一.数组的拷贝: 使用Arrays类的copyOf方法: 1.将一个数 ...

  6. linux内核中的最简单的输入输出调度算法noop

    1. noop是什么? noop是一种输入输出调度算法 2. noop的别称 又称为电梯调度算法 3. noop原理是怎样的? 将输入输出请求放到一个FIFO队列中,然后按次序执行队列中的输入输出请求 ...

  7. 记intel杯比赛中各种bug与debug【其一】:安装intel caffe

    因为intel杯创新软件比赛过程中,并没有任何记录.现在用一点时间把全过程重演一次用作记录. 学习 pytorch 一段时间后,intel比赛突然不让用 pytoch 了,于是打算转战intel ca ...

  8. cmd中pip加速的方法

    临时加速: pip install dlib -i https://pypi.tuna.tsinghua.edu.cn/simple/ 永久加速: 在user文件夹里新建pip文件夹,再建pip.in ...

  9. ACM、OI等比赛中的程序对拍问题

    多年前请教于ZXYTIM(zxy)大牛,现在把windows环境下的版本贴出来. 手动数据调试效率太低,程序对拍还是非常实用的,特别适用于OI.蓝桥杯等这些比赛规则.可以用于暴力与AC算法之间的对拍. ...

随机推荐

  1. POJ 3616 Milking Time ——(记忆化搜索)

    第一眼看是线段交集问题,感觉不会= =.然后发现n是1000,那好像可以n^2建图再做.一想到这里,突然醒悟,直接记忆化搜索就好了啊..太蠢了.. 代码如下: #include <stdio.h ...

  2. JS获取div高度的方法

    有时在写页面时,需要获取一个div的高度.怎么才能获取呢?哈哈,先上结论.有两种方法. offsetHeight .clientHeight getComputedStyle offsetHeight ...

  3. 求N个集合的并集

    做容器放置实验时,需要计算下载N个Images的总size(Image之间可能会有可以共享的size). 一开始想到的是Images两两之间求交集,然后慢慢推到了容斥原理...时间复杂度大概就是O(N ...

  4. PHP学习之工厂方法模式

    <?php //工厂方法模式 interface Doing { function eat(); function sleep(); } class Cat implements Doing { ...

  5. v-if与v-show的区别?

    v-if的显示和隐藏实在dom里创建和消除dom节点 v-show是用css样式的display来控制dom节点的显示和隐藏 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染 ...

  6. Android 显示系统:OpenGL简介和Gralloc代码分析

    一.OpenGL ES与EGL Android的GUI系统是基于OpenGL/EGL来实现的. 由于OpenGL是通用函数库,在不同平台系统上需要被“本土化”——把它与具体平台的窗口系统建立起关联,F ...

  7. C之输入输出

    %d - int%ld – long (long int)%lld - long long%hd – short 短整型 (half int) %c - char%f - float%lf – dou ...

  8. Linux Mint设置自定义快捷键

    我使用的是 Linux Mint 19.2 Tina 先搜索键盘,把键盘的功能调出来 快捷键--->>自定义快捷键--->>添加自定义快捷键 名称可自定义(这里我定义的是“截图 ...

  9. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_14.RabbitMQ研究-与springboot整合-搭建环境

    我们选择基于Spring-Rabbit去操作RabbitMQ https://github.com/spring-projects/spring-amqp 使用spring-boot-starter- ...

  10. 升级系统中的java到1.8版本

    (1).安装或升级java,并配置环境变量 注意:此处分为yum安装与rpm安装,区别在于yum安装省事但配置麻烦,rpm安装麻烦但配置省事. 1)yum安装 在安装前可以使用yum list ins ...