본문 바로가기

백준/백준

[ 백준 17390 ] 이건 꼭 풀어야 해!

1. 문제 링크 https://www.acmicpc.net/problem/17390

 

17390번: 이건 꼭 풀어야 해!

[2, 5, 1, 4, 3]을 비내림차순으로 정렬하면 [1, 2, 3, 4, 5]이다.

www.acmicpc.net

2. 문제 

3. 문제 요약

 비정렬 수열을 정렬하고, 범위의 합을 출력해라

 

4. 문제 풀이

(1)  1차원 배열의 정렬

 정렬은 딱히 설명할 게 없다.

 우선 문제를 풀기 위해서 임의의 순서로 들어오는 값들을 정렬할 필요가 있다.

 N(1≤N300,000)개의 데이터가 들어오는 만큼 O(N²)의 정렬법은 시간초과가 분명했기에,

 O(NlogN)의 복잡도를 갖는 방법으로 정렬하고자 해서, 퀵소트를 이용해서 정렬했다. 

 

(2) 배열의 부분 합 // 메모이제이션

  정렬 후, 주어지는 Q(1Q300,000)개의 줄에 제시되는 범위의 부분 합을 출력하면 된다.

  각 줄마다 반복문을 통해서 문제를 해결하려고 하면, O(QN)의 복잡도를 갖게 되어 역시 시간초과가 분명했다.

  그래서 각 범위에 대해서 미리 계산해두고 저장해둔 뒤, 필요한 범위를 바로바로 출력하는 방식을 쓰기로 했다.

 

(3) DP의 응용

 S[ a, b ] 를 배열의 닫힌 구간 [ a, b ]에서의 부분 합이라고 한다면, 마치 적분처럼

 S[ a, b ] = S[ 1, b ] - S[ 1, a-1 ] 과 동일하다.

 따라서, int[] sum을 선언하여, sum[i] 는 1번부터 i번까지의 합이라고 하면,

 각 질문마다 S[a,b] = sum[b] - sum[a-1] 을 이용하여 바로바로 구할 수 있다.

 

5. 풀이 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args) throws Exception {
    stk = new StringTokenizer(br.readLine());
    int N = Integer.parseInt(stk.nextToken());
    int Q = Integer.parseInt(stk.nextToken());
    int[] arr = new int[N + 1];
 
    stk = new StringTokenizer(br.readLine());
    for (int i = 1; i <= N; i++)
        arr[i] = Integer.parseInt(stk.nextToken());
 
    quickSort(arr, 1, N);
 
    int[] dp = new int[N + 1];
    for (int i = 1; i <= N; i++)
        dp[i] = arr[i] + dp[i - 1];
 
    while (Q-- > 0) {
        stk = new StringTokenizer(br.readLine());
        int head = Integer.parseInt(stk.nextToken());
        int tail = Integer.parseInt(stk.nextToken());
        int ans = dp[tail] - dp[head - 1];
        bw.write(ans + "\n");
    }
    bw.flush();
}
 
Colored by Color Scripter
 

'백준 > 백준' 카테고리의 다른 글

[ 백준 1000 ] A+B  (0) 2020.06.05
[ 백준 7576 ] 토마토  (0) 2019.11.30
[ 백준 9095 ] 1, 2, 3 더하기  (0) 2019.11.15
[ 백준 1966 ] 프린터 큐  (0) 2019.11.07
[ 백준 14648 ] 쿼리 맛보기  (0) 2019.11.06