C++

ios::sync_with_stdio(false), cin.tie(0) 쓰는 이유, 백준 시간초과 해결

DingCoDing 2022. 1. 24. 16:26
반응형

1. ios::sync_with_stdio(false), cin.tie(0) 은 무엇인가?

보통 백준, 프로그래머스 같은 온라인 저지 사이트에서 C++을 이용하여 알고리즘 문제를 풀 때

 

시간초과를 방지하기 위해서 이 두 줄을 추가해줍니다.

 

	ios::sync_with_stdio(false);
	cin.tie(0);

 

기존 입출력을 cin, cout, printf, scanf 함수를 이용해 했다가

 

cin과 cout만을 이용하고

 

이렇게 두 줄만 추가해주면 시간초과로 인해 틀렸던 문제가

 

맞는 경우가 종종 있습니다.

 

그 이유는 문제에서 입출력 양이 굉장히 많아지면,

 

입출력하는데 소모시간이 많아져서 시간초과가 발생하기 때문입니다.

 

위 코드를 작성하면 입출력 속도가 빨라지고, 그로인해 시간초과로 틀렸던 문제가 맞게 됩니다.

 

그렇다면 이 두줄의 의미는 무엇일까요?

 

 

 

1-1. ios::sync_with_stdio(false)

이 코드는 C와 C++ 표준 stream의 동기화를 비활성화합니다.

 

동기화가 활성화 되어있을 땐 C 스타일과 C++스타일의 입출력을 혼합해도 문제가 없습니다.

예를 들어 C스타일(printf scanf) C++스타일(cin cout)을 혼합하여 사용해도 문제가 없습니다.

 

하지만 이 코드를 작성하면 C 스타일과 C++ 스타일이 혼합할 수 없는 대신에,

C++ 스타일 코드만 사용하면 기존 동기화 과정에서 필요하던 시간이 절약되어

입출력 속도가 빨라지는 효과가 있습니다.

 

즉 알고리즘 문제를 풀 때는 표준 stream의 동기화는 필요없고 시간이 절약되는 게 우선이니

ios::sync_with_stdio(false)를 사용하여 입출력 시간을 절약할 수 있습니다.

 

다만 이 코드를 사용하면 기존 C의 표준 입출력인

scanf, printf, getchar 함수를 사용하면 오류가 발생할 수 있습니다.

C++의 입출력인 cin, cout만 사용하도록 주의해야합니다.

 

 

 

1-2. cin.tie(null)

cin.tie는 평소 cin과 cout을 묶어줍니다. 

cout << "Write your name, please \n" <<;
cin >> name;

이런 코드가 있다면

 

평소에는 cin과 cout이 하나로 묶어져 있어서 

"Write your name, please \n" 가 반드시 먼저 출력된 후 이름을 입력할 수 있습니다.

 

그러나 cin.tie(0)이나 cin.tie(null) 코드를 추가해 주면

"Write your name, please \n" 출력이 되기 전에 이름을 입력할 수 있습니다.

내부적으로 cin과 cout을 묶어주는 과정을 수행하지 않기 때문에 시간이 절약됩니다.

 

다른 프로그램에서 이렇게 사용한다면 이름을 입력해달라고 요구하기 전에

입력을 할 수 있는 자연스럽지 못한 프로그래밍일 수 있습니다.

 

그러나 알고리즘 문제를 풀 때는 크게 상관이 없고,

입출력 시간을 절약할 수 있기 때문에 cin.tie(0) 코드를 많이 사용합니다.

 

 

2. ios::sync_with_stdio(false), cin.tie(0) 사용 효과

입출력 시간을 백준에서 비교한 글이 있습니다.

 

백준 입력속도비교
백준 출력 속도 비교

 

확실히

 

	ios::sync_with_stdio(false);
	cin.tie(0);

이 코드를 사용하여 입출력을 하면

 

보다 빠른 속도로 입출력을 할 수 있는 것을 알 수 있습니다.

 

출처입니다.

https://www.acmicpc.net/blog/view/56

 

입력 속도 비교

여러가지 언어와 입력 방법을 이용해서 시간이 얼마나 걸리는지 비교해 보았습니다. 방법: 첫째 줄에 정수의 개수 N (= 10,000,000), 둘째 줄부터 N개의 줄에 한 개의 자연수(10,000 이하)가 적힌 파일

www.acmicpc.net

 

 

3. scanf, printf vs cin, cout

scanf printf 와 cin cout을 비교하면

 

일반적으로 scanf printf가 cin cout보다 속도가 빠르지만,

	ios::sync_with_stdio(false);
	cin.tie(0);

이 코드를 추가하고 cin cout을 사용하면 기존의 scanf printf 속도보다 빨라집니다.

 

코테나 알고리즘 문제를 풀 때 입출력 시간을 절약하기 위해서

 

위 코드와 함께 cin cout을 이용해서 프로그래밍 하는 것이 좋습니다.

 

 

etc

입출력할 때 개행을 하려면 

endl 대신 '\n' 을 사용해야 시간을 절약할 수 있습니다.

 

std::cout<<ans<<std::endl;
std::cout << ans << '\n';

 

 

 

stackoverflow 사이트에 게시된

ios::sync_with_stdio(false),  cin.tie(0)와 관련한 글입니다.

 

이 글의 답변 내용 중

 

"The two calls have different meanings that have nothing to do with performance; the fact that it speeds up the execution time is (or might be) just a side effect. You should understand what each of them does and not blindly include them in every program because they look like an optimization."

 

"두 호출은 성능과 아무 관련이 없는 다른 의미를 갖습니다.

실행 시간을 단축한다는 사실은 단지 부작용일 뿐입니다.

최적화처럼 보이기 때문에 각각의 기능을 이해하고

모든 프로그램에 맹목적으로 포함하지 않아야 합니다."

 

즉 이 코드는 웬만하면 알고리즘 문제를 풀 때 시간절약하기 위해서 사용하는 것이지,

모든 프로그램에 입출력 시간을 절약하기 위해서 사용하는 올바른 방법은 아님

말하고 있습니다.

 

참고하셔서 사용하면 좋을 것 같아요.

 

https://stackoverflow.com/questions/31162367/significance-of-ios-basesync-with-stdiofalse-cin-tienull

 

Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);

What is the significance of including ios_base::sync_with_stdio(false); cin.tie(NULL); in C++ programs? In my tests, it speeds up the execution time, but is there a test case I should be worried...

stackoverflow.com

 

 

읽어주셔서 감사합니다.