zoukankan      html  css  js  c++  java
  • 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
    ",double(clock()-s)/CLOCKS_PER_SEC);
    }

    cin的速度
    可以看出,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
    ",double(clock()-s)/CLOCKS_PER_SEC);
    }

    cin的优化
    时间变成了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
    ",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
    ",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,尽量用手写的快速读入来读取
    版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢
  • 相关阅读:
    VC实现开机自启动
    用Shell扩展实现源代码统计程序
    在(CListView)列表视图中添加右键菜单的方法
    关于打开外部程序并且发送一个按键消息 (转
    vc中运行外部程序的方法
    如何在 XCode 4.2 設定部分程式碼不使用 ARC 方式分享(转)
    Xcode调试断点不停止解决方案!(转)
    NSString+NSMutableString+NSValue+NSAraay用法汇总 (转)
    对于Retain和Assign属性的理解(转)
    基于Xcode4开发第一个iPhone程序:“Hello World”(转)
  • 原文地址:https://www.cnblogs.com/birchtree/p/9845856.html
Copyright © 2011-2022 走看看