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. P1169 [ZJOI2007]棋盘制作——悬线法

    ---恢复内容开始--- 给你一个矩阵,选出最大的棋盘,棋盘的要求是黑白相间(01不能相邻),求出最大的正方形和矩形棋盘的面积: 数据n,m<=2000; 这个一看就可能是n2DP,但是写不出. ...

  2. laotech老师唠科mac 深入浅出MAC OS X ceshi ruguokeyi

    laotech老师唠科mac 深入浅出MAC OS X http://study.163.com/plan/planLearn.htm?id=1637004#/learn/resVideo?lesso ...

  3. leveldb源码分析之内存池Arena

    转自:http://luodw.cc/2015/10/15/leveldb-04/ 这篇博客主要讲解下leveldb内存池,内存池很多地方都有用到,像linux内核也有个内存池.内存池的存在主要就是减 ...

  4. IDEA算法导包后 import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey;报错

    仔细查看报错原因就能知道,报错是因为包冲突的原因,可以每种只放一个jar包,就能过避免这种错误. 例如:只导入commons-codec-1.11-javadoc,jar和bcprov-jdk15on ...

  5. jmeter如何使用正则表达式,如何提取token等想要的数据

    使用正则表达式,提取你想要的任何数据, 例如要提取响应结果里的token字段及sex字段(响应内容为: "token":"83EEAA887F1D2F1AA1CDA9E1 ...

  6. 学python必须知道的30个技巧

    收集这些有用的捷径技巧 1. 原地进行交换两个数字 我们对赋值的右侧进行一个新的元组,左侧解析(unpack)那个(未被引用的)元组到变量 <a> 和 <b> 赋值完成时,新的 ...

  7. Hype-v创建服务器实例

    1.创建虚拟交换机,如下图所示(虚拟交换机,只需要创建一次,后面增加服务器实例的时候,只需要选择这个虚拟交换机就可以了,不用每次都创建) 2.服务器主网络共享给虚拟交换机,如下图所 3.虚拟交换机的I ...

  8. err="etherbase address must be explicitly specified"

    如果要初始化区块链的话就用创始区块   如果通过创世区块来初始化区块链的话,首先需要一个初始化区块链的json文件,如下. { "config": { "chainId& ...

  9. java工厂模式的测试

    /** * 工厂模式的测试 * <p> * 工厂方法模式 * 工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽 ...

  10. vue开发(一)安装

    1.安装nodejshttps://nodejs.org/zh-cn/ 2.vs2019  工具-获取工具和功能 勾选nodejs开发并安装 3.新建基于vuejs web应用程序 4.右键项目在此处 ...