개발자공부일기
11659번 - 구간 합 구하기 4(C++) 본문
https://www.acmicpc.net/problem/11659
수 N개가 주어졌을 때, i번째 수부터 j번째 수까지 합을 구하는 프로그램을 작성하는 구간 합 문제다.
아래처럼 풀었는데 시간초과가 난다. 디버깅을 해봤을때 결과는 다 맞다. 뭔가를 최적화해야한다는 뜻이다.
#include <iostream>
using namespace std;
int main(){
int dataCnt,quizCnt;
int arr[100001]={};
cin>>dataCnt>>quizCnt;
for(int i=1;i<=dataCnt;i++){
int temp;
cin>>temp;
arr[i]=arr[i-1]+temp;
}
for(int i=0;i<quizCnt;i++){
int start, end;
cin>>start>>end;
cout<<arr[end]-arr[start-1]<<endl;
}
return 0;
}
그래서 질문게시판을 봤는데 나같은 경우가 굉장히 많았다.
int main() {
ios::sync_with_stdio(false); // 추가
cin.tie(nullptr) // 추가
int n,order,start,end,temp;
(중략)
cout<<solve(sumArr,start,end)<< "\n" // endl을 개행문자로
저 문구들을 추가하면 된다는 글을 봤고 아래처럼 나에게 맞게 수정했다.
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int dataCnt,quizCnt;
int arr[100001]={};
cin>>dataCnt>>quizCnt;
for(int i=1;i<=dataCnt;i++){
int temp;
cin>>temp;
arr[i]=arr[i-1]+temp;
}
for(int i=0;i<quizCnt;i++){
int start, end;
cin>>start>>end;
cout<<arr[end]-arr[start-1]<<"\n";
}
return 0;
}
그랬더니 시간초과가 안나온다! 그래서 저 추가된 3줄의 코드는 무엇이며 endl대신 개행을 써야하는 이유는 무엇일까?
1. ios::sync_with_stdio(false);
- C++의 cin, cout은 기본적으로 C의 scanf, printf와 동기화(sync)되어 있습니다.
- 이 동기화는 안정성은 주지만 속도가 느려지게 됩니다.
- false로 설정하면 cin/cout이 더 이상 scanf/printf와 동기화되지 않아 입출력이 빨라집니다.
- 단점: 이후에는 cin과 printf, 또는 scanf와 cout을 혼용하면 안 됩니다. 이상한 동작이 생길 수 있어요.
✔ cin과 cout만 쓸 거면 false로 꺼주는 것이 빠름
2. cin.tie(NULL);
- 기본적으로 cin은 cout에 묶여(tied) 있어서, cin을 호출하기 전에 cout의 출력 버퍼를 지우는 작업을 합니다.
- 이 묶임을 끊어주면 불필요한 작업을 줄여서 속도를 향상시킬 수 있습니다.
✔ cin이 cout을 기다리지 않게 해서 속도를 높임
3. cout.tie(NULL);
- 실제로 잘 사용되지 않지만, cout과 다른 스트림(ex. cerr) 사이의 tie를 끊는 경우도 있습니다.
- 대부분은 영향이 적지만, 작성하는 습관에 따라 추가로 넣기도 합니다.
✔ 거의 영향 없지만 혹시 모를 다른 스트림 간의 tie를 끊음
4. endl대신 개행문자
endl과 \n은 둘 다 줄바꿈을 하지만, 중요한 차이가 하나 있습니다.
차이점 요약
구분 | endl | \n |
기능 | 줄바꿈 + 버퍼 flush | 줄바꿈만 |
성능 | 느림 (flush 때문에) | 빠름 |
용도 | 즉시 출력이 필요한 경우 사용 | 대량 출력 시 선호 |
🔍 자세히 설명
endl
cout << "Hello" << endl;
- 줄바꿈 (\n)을 출력하고,
- 출력 버퍼를 즉시 비움 (flush)
→ 이 때문에 출력 성능이 떨어질 수 있음
\n
cout << "Hello\n";
- 줄바꿈만 수행 (출력 버퍼는 그대로 유지됨)
- 나중에 cout이 충분히 쌓이거나 flush 또는 endl이 호출되었을 때 한꺼번에 출력
🔧 성능 테스트 예
// 느린 예 (flush 매번 발생)
for (int i = 0; i < 1000000; ++i)
cout << i << endl;
// 빠른 예 (flush 없음)
for (int i = 0; i < 1000000; ++i)
cout << i << '\n';
endl 버전은 매번 버퍼를 비우기 때문에 훨씬 느려요.
전부 버퍼를 비우는 작업을 줄임으로써 시간을 단축하는 코드들이 되겠다.
시간제한이 매우 짧은 문제들에서 사용하면 유용할듯하다.
'코딩테스트 > 백준' 카테고리의 다른 글
11003번 - 최솟값 찾기(c++) (0) | 2025.07.25 |
---|---|
10986번 - 나머지 합 구하기 5(C++) (0) | 2025.06.04 |
11660번 - 구간 합 구하기 5(C++) (0) | 2025.05.01 |