NOIP比赛中如何加速c++的输入输出
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,比其他的方法都快,而且不会在评测机上出现问题,并且也没有调用许多函数
遇到数据量大的题,尽量用手写的快速读入来读取
总结
- 遇到大数据时尽量避免用cin
- noip比赛中坚决不要写std::ios::sync_with_stdio(false)来优化cin
- 如果是double或输入格式较复杂用scanf
- 遇到数据量大的题,且是long long或int,尽量用手写的快速读入来读取
NOIP比赛中如何加速c++的输入输出的更多相关文章
- [ACM训练] ACM中巧用文件的输入输出来改写acm程序的输入输出 + ACM中八大输入输出格式
ACM中巧用文件的输入输出来改写acm程序的输入输出 经常有见大神们使用文件来代替ACM程序中的IO,尤其是当程序IO比较复杂时,可以使自己能够更专注于代码的测试,而不是怎样敲输入. C/C++代码中 ...
- 新手数据比赛中数据处理方法小结(python)
第一次参加,天池大数据竞赛(血糖预测),初赛排名1%.因为自己对python不熟悉,所以记录一下在比赛中用到的一些python方法的使用(比较基础细节,大佬绕道): 1.数据初探 data.info( ...
- 【CTF 攻略】CTF比赛中关于zip的总结
[CTF 攻略]CTF比赛中关于zip的总结 分享到: --> 本文首发于安全客,建议到原地址阅读,地址:http://bobao.360.cn/ctf/detail/203.html 前言 ...
- java:比赛中常用方法整理——字符串(基础)
一.将字符串转化为字符数组: toCharArray返回一个字符数组. char[] a=J.toCharArray(); 二.字符串的长度 字符串的长度和字符数组的长度是不一'样'的. 字符串长度( ...
- java:编程比赛中有用的方法整理(一)数组
我曾经参加过几次编程比赛,但是当时用的是c语言,现在学习了java,打算专攻java组,故以此整理. 数组无论在哪里都必不可少. 一.数组的拷贝: 使用Arrays类的copyOf方法: 1.将一个数 ...
- linux内核中的最简单的输入输出调度算法noop
1. noop是什么? noop是一种输入输出调度算法 2. noop的别称 又称为电梯调度算法 3. noop原理是怎样的? 将输入输出请求放到一个FIFO队列中,然后按次序执行队列中的输入输出请求 ...
- 记intel杯比赛中各种bug与debug【其一】:安装intel caffe
因为intel杯创新软件比赛过程中,并没有任何记录.现在用一点时间把全过程重演一次用作记录. 学习 pytorch 一段时间后,intel比赛突然不让用 pytoch 了,于是打算转战intel ca ...
- cmd中pip加速的方法
临时加速: pip install dlib -i https://pypi.tuna.tsinghua.edu.cn/simple/ 永久加速: 在user文件夹里新建pip文件夹,再建pip.in ...
- ACM、OI等比赛中的程序对拍问题
多年前请教于ZXYTIM(zxy)大牛,现在把windows环境下的版本贴出来. 手动数据调试效率太低,程序对拍还是非常实用的,特别适用于OI.蓝桥杯等这些比赛规则.可以用于暴力与AC算法之间的对拍. ...
随机推荐
- AcWing:242. 一个简单的整数问题(树状数组)
给定长度为N的数列A,然后输入M行操作指令. 第一类指令形如“C l r d”,表示把数列中第l~r个数都加d. 第二类指令形如“Q X”,表示询问数列中第x个数的值. 对于每个询问,输出一个整数表示 ...
- Fiddler 安装使用
Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的小功能 ...
- CentOS7根目录磁盘扩容(/dev/mapper/centos-root 空间不足)
今天在给测试环境搭建k8s系统时,发现master根目录磁盘空间不足,需要扩容,记录如下. # 查看根分区大小 [root@master ~]# df -h Filesystem Size Used ...
- HDU 2859 Phalanx ——(DP)
感觉是个n^3的dp,只是可能上界比较松吧..转移见代码.值得注意的一个地方是如果n是1,那么在for里面是不会更新答案的,因此ans要初始化为1. 代码如下: #include <stdio. ...
- mac使用技巧汇总
1.在屏幕锁屏的时候,加入提示信息 sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText &qu ...
- mysql —日志记录
日志 事务日志: transaction log 中继日志: reley log错误日志: error log 通用日志: general log 慢查询日志: slow query log 二进制日 ...
- spring-boot学习 (Groovy与Spring Boot Cli)
一.使用idea创建一个spring-boot项目,选择groovy语言 二.编写相应代码 1.创建实例类 package com.zhi.example class Man { Long id St ...
- P1944 最长括号匹配_NOI导刊2009提高(1)
P1944 最长括号匹配_NOI导刊2009提高 题解 宁愿相信世上有鬼,也不能随便相信某谷题目标签 我想了半天然后看了眼题解,发现用栈来模拟就好了 栈来模拟,还要用到一个bool数组,标记是否已经匹 ...
- 《你不知道的JavaScript(上)》笔记——动态作用域
动态作用域让作用域作为一个在运行时就被动态确定的形式, 而不是在写代码时进行静态确定的形式.动态作用域并不关心函数和作用域是如何声明以及在何处声明的, 只关心它们从何处调用. 换句话说, 作用域链是基 ...
- 重学C语言
重学C语言 #include <stdio.h> int main() { ; ; printf("I am %d year old.\n",age); printf( ...