개발자공부일기

11659번 - 구간 합 구하기 4(C++) 본문

코딩테스트/백준

11659번 - 구간 합 구하기 4(C++)

JavaCPP 2025. 4. 30. 10:00

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