Loading [MathJax]/jax/output/HTML-CSS/jax.js

ABOUT ME

Today
Yesterday
Total
  • 363-B, *1100
    코드포스 2021. 7. 22. 21:27
     

    Problem - 363B - Codeforces

     

    codeforces.com

    문제

    • n(1n1.5105)개의 수가 나열되어 있다
    • 연속된 k개의 수의 합이 가장 작은부분은 어디인가?
    • O(nlog n) 정도 알고즘은 통과할 수 있다

     

    O(n)

    누적합을 저장하는 배열(acc)을 만들면 O(n)
    acc[i]acc[ik]
    을 이용하여 ik+1부터 i까지 원소의 합을 구할 수 있다
    이제 모든 경우에 대해 값을 비교하여 최솟값을 구한다 O(nk)

    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
    #include <bits/stdc++.h>
    #define endl "\n"
    using namespace std;
     
    int h[200000];
    int acc[200000];
     
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0), cout.tie(0);
     
        int n, k;
        int tmp;
     
        cin >> n >> k;
        for(int i = 1; i <= n; i++cin >> h[i];
     
        acc[1= h[1];
        for(int i = 2; i <= n; i++) acc[i] = acc[i-1+ h[i];
     
        int minval = 20000000;
        int minval_ind = 1;
     
        for(int i = k; i <= n; i++) {
            if(minval > acc[i]-acc[i-k]){
                minval = acc[i]-acc[i-k];
                minval_ind = i-k+1;
            }
        }
     
        cout << minval_ind << endl;
     
        return 0;

     

    O(nk)

    s를 배열a 앞에서부터 k개의 수의 합이라 하자
    s=ki=1ai
    sa[k+1]를 더하고 a[1]을 빼면 2번째 수부터 k+1번째 수까지의 합을 구할 수 있다 O(1)
    다시 sa[k+2]를 더하고 a[2]을 빼면 3번째 수부터 k+2번째 수까지의 합을 구할 수 있다 O(1)
    같은방법으로 nk번 반복한다 O(nk)

    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
    #include <bits/stdc++.h>
    #define endl "\n"
    using namespace std;
     
    int arr[200000] {};
     
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0), cout.tie(0);
     
        int n, k;
        cin >> n >> k;
        for(int i = 1; i <= n; i++cin >> arr[i];
     
        int s = accumulate(arr+1, arr+k+10);
        int minval = s;
        int minval_ind = 1;
        for(int i = 1; i <= n-k; i++){
            s = s + arr[i+k] - arr[i];
            if(s < minval){
                minval = s;
                minval_ind = i+1;
            }
        }
     
        cout << minval_ind << endl;
     
        return 0;

     

    시간초과

    배열(a)의 앞에서부터 매번 k개의 원소를 더한 값을 비교하는 brute force 를 시행하는 경우를 보자
    a[i]+a[i+1]++a[i+k1]i=0,1,2,,nk
    더하는데 k번의 연산이 필요하고, nk번 비교를 하므로
    O(k(nk))의 수행시간이 드는데 n=1.5105, k=n/2 이면
    대략 5.6109 번 연산을 하므로 시간초과이다

    '코드포스' 카테고리의 다른 글

    456-A, *1100  (0) 2021.07.23
    519-B, *1100  (0) 2021.07.23
    270-A, *1100  (0) 2021.07.22
    706-B, *1100  (0) 2021.07.22
    158-B, *1100  (0) 2021.07.21

    댓글

Designed by Tistory.