ed1d1a8d's blog

By ed1d1a8d, 11 years ago, In English

What form of I/O should we use in competitive programming?

For example scanf and printf are undoubtedly faster than cin and cout, but the later two are easier and faster to code. How should we adress this tradeoff?

  • Vote: I like it
  • 0
  • Vote: I do not like it

| Write comment?
»
11 years ago, # |
  Vote: I like it +1 Vote: I do not like it

Just include std::ios::sync_with_stdio(false); in your code, and cin will be as fast as scanf.

  • »
    »
    11 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    In which part of the code?

  • »
    »
    10 years ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    Then mukel why isn't it there by default? Any disadvantages of the same?

    • »
      »
      »
      10 years ago, # ^ |
      Rev. 2   Vote: I like it +3 Vote: I do not like it

      You can't use both cin/cout and printf/scanf.

      • »
        »
        »
        »
        5 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        Technically, one can still use both cin/cout and scanf/printf together, but will have to manually handle flushing the buffer(s), which is tedious.

  • »
    »
    9 years ago, # ^ |
      Vote: I like it +10 Vote: I do not like it

    But I have seen different cases.

    Check this two submissions of me: 11250063 and 11224282.

    First one was TLE though I used what you recommended.

    • »
      »
      »
      9 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      The problem is the output, cout << endl flushes the output every time wich hit performance badly. To output an end line without flushing just use #define endl '\n'

      • »
        »
        »
        »
        9 years ago, # ^ |
        Rev. 2   Vote: I like it 0 Vote: I do not like it

        Yeah I got that. Actually I have tried that also. It works.

        Now my question is, if I do everything as recommended about cin/cout, will it be enough to solve all problems?

        I find that confusing.

        Just a few minutes ago, I have solved this problem at spoj: http://www.spoj.com/ranks/INVCNT/start=20

        This is a simple problem of counting inversions. I just implemented BIT.

        By the way, the thing is, I made three submissions for the problem. Check out this screenshot:

        So you can see the difference. The first one was using scanf/printf. Second one was with cin/cout+sync_with_stdio and the third one used just cin/cout.

  • »
    »
    9 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    It happened in Round #304 Div2 Problem D.

    I submitted the problem with cin, cout and used std::ios::sync_with_stdio(false);

    The submission with cin, cout got TLE on 3rd testcase:

    Link: http://codeforces.com/contest/546/submission/11225677

    whereas the same solution passed with scanf and printf.

    Link: http://codeforces.com/contest/546/submission/11342025

    Can you explain why this happened?

  • »
    »
    8 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Using std::ios::sync_with_stdio(false); on SPOJ gave Runtime error for this problem. By removing std::ios::sync_with_stdio(false); it got accepted. Why?

    • »
      »
      »
      8 years ago, # ^ |
        Vote: I like it +9 Vote: I do not like it

      You should not mix cin/cout and scanf/printf once you have that "magic" line :)

»
11 years ago, # |
  Vote: I like it +12 Vote: I do not like it

Like mukel said, ios_base::sync_with_stdio(0) makes c++ io streams' performance comparable to cstdio's. Have a look at the following thread: http://codeforces.com/blog/entry/925, as well as here: The Standard Librarian: IOStreams and Stdio.

Once, at another Online Judge, I kept getting TLE's for an algorithm that was quite IO intensive. I was using cin/cout and ios_base::sync_with_stdio(0) as the first line of main()'s body. I switched back to scanf/printf and got AC. Depends on the implementation. To me, it works wonderfully at CodeForces.

PD:Also, favor '\n' instead of endl for ending lines. endl flushes the buffer every time.

  • »
    »
    11 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Does this apply to all streams? i.e. reading files with ifstream or ofstream

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it +1 Vote: I do not like it

      ios_base::sync_with_stdio() only affects standard streams; there's probably nothing you can do to speed up ifstream/ofstream, except for not using endl or changing their buffer sizes.

      • »
        »
        »
        »
        10 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        But fstream is even faster than iostream with ios_base::sync_with_stdio()

        • »
          »
          »
          »
          »
          10 years ago, # ^ |
            Vote: I like it 0 Vote: I do not like it

          This is placebo. The function only affects standard streams. In case of fstream there is not even a corresponding C stream to synchronize with.

»
11 years ago, # |
  Vote: I like it +5 Vote: I do not like it

but also notice: with std::ios::sync_with_stdio(false);, don't mix C-style IO (scanf/printf, gets/puts, getchar/putchar ... ) with C++-style IO (cin/cout ... ), since cin/cout is not sync with stdio, you may get same data from using scanf and then use cin again.

»
11 years ago, # |
  Vote: I like it 0 Vote: I do not like it

You might find this post of mine useful: http://codeforces.com/blog/entry/5217

»
11 years ago, # |
  Vote: I like it 0 Vote: I do not like it
»
10 years ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

Put this: ios_base::sync_with_stdio(false);cin.tie(0); in the beggining of the main func. cin/cout will be as fast as scanf and printf (even faster). BUT DONT USE ENDL (use "\n")

  • »
    »
    10 years ago, # ^ |
      Vote: I like it +4 Vote: I do not like it

    Put #define endl '\n', and you don't need to worry about it anymore :)

  • »
    »
    9 years ago, # ^ |
      Vote: I like it +3 Vote: I do not like it

    Check this I have used endl with ios_base::sync_with_stdio(false);cin.tie(0); and it worked.

    • »
      »
      »
      9 years ago, # ^ |
        Vote: I like it +3 Vote: I do not like it

      try it in a problem which requires you to answer 10^5 or more queries. this question doesnt require fast I/O. try this problem http://codeforces.com/contest/456/problem/E just copy any accepted C++ solution and submit it with endl and ios_base::sync_with_stdio(false);cin.tie(0); it will fail. check my submission history.

»
10 years ago, # |
  Vote: I like it 0 Vote: I do not like it

I use stringstream to store output first and output it on the last line as cout << ss.str();.

This works great when you input and output alternatively. (For example, when you output as you answer query)

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

fastest I is getchar_unlocked()

  • »
    »
    9 years ago, # ^ |
      Vote: I like it +19 Vote: I do not like it

    just found out this blog is 2 years old ;|

    • »
      »
      »
      9 years ago, # ^ |
        Vote: I like it +10 Vote: I do not like it

      Two years old, but no one else said anything about getchar_unlocked =P.

      It was really hard to convince myself to move from C to C++ half a decade ago, but I did. I never liked cin/cout though, so I still use scanf/printf instead, and that probably won't change.

      In the very rare times I need fast input reading (like when the input size is O(n) and an O(n) solution is expected, but mine is O(n lg n)): for (x = 0; (c = getchar_unlocked()) >= '0'; x = x*10+c-'0'); // reads int to x

      Usually I write it as the following function:

      inline void scan_uint(int* p) {
          static char c;
          while ((c = getchar_unlocked()) < '0'); // just to be safe
          for (*p = c-'0'; (c = getchar_unlocked()) >= '0'; *p = *p*10+c-'0');
      }
      

      Making it parse input as float, string, int with sign, return if eof, etc should be easy too... getchar_unlocked already gave me two or three balloons, so I'm grateful to it =)!

      • »
        »
        »
        »
        9 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        getchar_unlocked gave CE on CF. Would you please check?

        11338997

        • »
          »
          »
          »
          »
          9 years ago, # ^ |
            Vote: I like it 0 Vote: I do not like it

          i don't know since i haven't worked with getchar_unlocked() but i know it is the best form of getting input

        • »
          »
          »
          »
          »
          9 years ago, # ^ |
            Vote: I like it 0 Vote: I do not like it
          • »
            »
            »
            »
            »
            »
            9 years ago, # ^ |
            Rev. 2   Vote: I like it 0 Vote: I do not like it

            You are right =). I didn't even know CF used Windows system! O.o I remember having used getchar_unlocked on CF in the past, but I'm probably wrong then.

            I use Windows on my machine because I play a lot, and it's incovenient to keep rebooting. So, what I did was to add the following line to my stdio.h: #define getchar_unlocked getchar

            About it not working on CF, though, there is nothing we can do =/.

            P.S.: using getchar is still faster than scanf, of course. But it usually isn't fast enough to make the difference (make a TLE become an AC).

»
9 years ago, # |
Rev. 3   Vote: I like it +14 Vote: I do not like it

I use this recently, and work very good :


using namespace std; typedef long long i64; const int MAX_STRING_LENGTH = 1; #define endl "\n" struct _io{ char buff[MAX_STRING_LENGTH]; _io & operator >>(int &x){ scanf("%d",&x); return *this; } _io & operator >>(i64 &x){ scanf("%I64d",&x); return *this; } _io & operator >>(float &x){ scanf("%f",&x); return *this; } _io & operator >>(double &x){ scanf("%lf",&x); return *this; } _io & operator >>(long double &x){ scanf("%llf",&x); return *this; } _io & operator >>(char &c){ scanf("%c",&c); return *this; } _io & operator >>( char *s ){ scanf("%s",s); return *this; } _io & operator >>( string &s ){ scanf("%s",buff); s = string(buff,strlen(buff)); return *this; } _io & operator <<(int x){ printf("%d",x); return *this; } _io & operator <<(i64 x){ printf("%I64d",x); return *this; } _io & operator <<(float x){ printf("%f",x); return *this; } _io & operator <<(double &x){ printf("%lf",x); return *this; } _io & operator <<(long double &x){ printf("%llf",x); return *this; } _io operator <<(char &c){ printf("%c",c); return *this; } _io & operator <<( string &s ){ printf("%s",s.c_str()); return *this; } _io & operator <<( char *s ){ printf("%s",s); return *this; } }io; int main(){ int a, b; io>>a>>b; io<<(a+b)<<endl; }
»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Hey guys, thanks for such an excellent discussion. I've read the entire page, but forgive me if I missed something, as I am going to ask a stupid question. * What if sometimes I want to use cin cout and sometimes printf, scanf etc. in the same code ? I mean, can I switch ON / OFF std::ios::sync_with_stdio(); whenever I want ?

  • »
    »
    9 years ago, # ^ |
      Vote: I like it +3 Vote: I do not like it

    You wouldn't want to switch off the sync and then use both cin/cout and scanf/printf as it "may result in unexpectedly interleaved characters".

    As it has been thoroughly explained above, cin/cout with syncing off and '\n' instead of endl should be faster than scanf / printf because the latter should undergo parsing all the time.

    You must call the function before any input / output is done, so no, you shouldn't be toggling it.

»
8 years ago, # |
  Vote: I like it +5 Vote: I do not like it

I don't like tradeoffs, so I ended up writing my own version http://codeforces.com/blog/entry/45835

»
6 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Before few minutes, I have solved Light oj problem no: 1087,problem title: "Diablo". In that problem, at first, I have used cin/count along with ios_base::sync_with_stdio(false);cin.tie(0);. I have also used #define endl "\n" and used no printf/scanf, which gave me Runtime Error. Later on, I have given up only this part cin.tie(0); and everything was similar like the before which gave me Time Limit Exceed. At last, I have used only printf/scanf which gave me Accepted.

Can any body explain it? (Thanks In Advance)

  • »
    »
    4 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I also had same experience for light oj problem no. 1088. Please explain if anybody knows why?? is it platform issue or something else??

    • »
      »
      »
      4 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      LightOJ has some weird issues with fast IO. Use scanf/printf in LightOJ and you should be fine.