Блог пользователя ed1d1a8d

Автор ed1d1a8d, 12 лет назад, По-английски

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?

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

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

»
12 лет назад, # |
  Проголосовать: нравится +12 Проголосовать: не нравится

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://mirror.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.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

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

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      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 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

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

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

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

»
12 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

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.

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

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

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
»
10 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

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 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

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 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

fastest I is getchar_unlocked()

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится +19 Проголосовать: не нравится

    just found out this blog is 2 years old ;|

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится +10 Проголосовать: не нравится

      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 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        getchar_unlocked gave CE on CF. Would you please check?

        11338997

        • »
          »
          »
          »
          »
          9 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

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

        • »
          »
          »
          »
          »
          9 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          • »
            »
            »
            »
            »
            »
            9 лет назад, # ^ |
            Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

            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 лет назад, # |
Rev. 3   Проголосовать: нравится +14 Проголосовать: не нравится

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 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

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 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    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 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

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

»
6 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

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)

  • »
    »
    5 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

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

    • »
      »
      »
      5 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

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