ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [1806] 부분합
    BOJ 2021. 9. 2. 10:38

    https://www.acmicpc.net/problem/1806

     

    1806번: 부분합

    첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.

    www.acmicpc.net

    <문제>

    브루트포스로 풀 수 있을까? 구간 (s,e)를 정하고, s의 범위는 (1,n), e의 범위도 (1,n)정도이다.

    고로 O(N^2)의 시간복잡도를 갖는다. 

    N이 10만, 시간제한이 0.5초이므로 O(NlogN)이하의 시간복잡도를 가져야만 TLE없이 해결할 수 있다.

     

    정렬을 한 후 -> O(NlogN) 이분탐색을 수행하면(logN) 시간내에 해결할 수 있을지는 모르지만, 이 문제는 입력되는 수열을 그대로 유지한 상태에서 탐색해야한다. 

     

    그렇기에 이 문제는 투포인터를 통해, 불필요한 부분은 더 탐색하지 않도록 만들것이다. 

    대략 아래의 경우의 수를 생각해볼 수 있을것이다. L, R은 둘다 0으로 초기화한다.

    1) 구간 (L,R)의 합이 S 미만인 경우 

    -> 합을 더 크게해야 하므로 R++

    2) 구간 (L,R)의 합이 S 이상인 경우

    -> 정답의 가능성이 있으므로 최적해를 업데이트한다. 이후 더 짧은 경우를 찾기 위해 L++

     

    동시에, L가 R보다 오른쪽에 존재하지 않도록, L와 R이 범위를 벗어나지 않도록 만들어주는 부분을 추가하면 된다.

    <소스코드>

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    int n, s;
    int a[100001];
    const int INF=2121212121;
    int main(void) {
        int i, j,left,right,len=INF,min_len=INF,sum=0;
        scanf("%d %d"&n, &s);
        for (i = 0; i < n; i++) {
            scanf("%d"&a[i]);
            if (a[i] >= s) {
                printf("1");
                return 0;
            }
        }
        sum = a[0];
        left = 0;
        right = 0;
        while (left <= right && right <= n-1) {
            if (sum < s && right < n) {
                right++;
                sum += a[right];
            }
            else if (sum >= s) {
                len = right - left + 1;
                min_len = min(len, min_len);
                if (left <= right) {
                    sum -= a[left];
                    left++;
                }
            }
        }
        if (min_len == INF)printf("0");
        else printf("%d", min_len);
        return 0;
    }
    cs

     

     

     

    'BOJ' 카테고리의 다른 글

    [1600] 말이 되고픈 원숭이  (0) 2021.09.05
    [17142] 연구소 3  (0) 2021.09.02
    [17609] 회문  (0) 2021.09.02
    [2568] 전깃줄 - 2  (0) 2021.09.02
    [1629] 곱셈  (0) 2021.09.02

    댓글