こんにちは、ナナオです。

前回に引き続き競プロを実施していきたいと思います。

今回の問題は以下です。

累積和の計算 | レベルアップ問題集 | プログラミング学習サイト【paizaラーニング】

実装

以下のように実装しました。

package main
import "fmt"
func main(){
    var n, m int
    fmt.Scan(&n, &m)
    x := 0
    a := make([]int, n)
    s := make([]int, n)
    for i := 0; i < n; i++ {
        fmt.Scan(&a[i])
        x += a[i]
        s[i] = x
    }
    if x < m {
        fmt.Println(-1)
        return
    }
    z := 100000
    for l := 0; l < n; l++ {
        for r := n - 1; r >= 0; r-- {
            sum := s[r] - s[l] + a[l]
            if sum >= m && z > r - l + 1 {
                z = r - l + 1
            }
        }
    }
    fmt.Println(z)
}

ですが、これだと計算量が多く実行時間エラーになってしまいました。

ということで、AIと壁打ちして「しゃくとり法」で実装しました。

package main
import "fmt"
func main(){
    var n, m int
    fmt.Scan(&n, &m)
    a := make([]int, n)
    for i := 0; i < n; i++ {
        fmt.Scan(&a[i])
    }
    
    z := n + 1
    sum := 0
    l := 0
    for r := 0; r < n; r++ {
        sum += a[r]
        
        for sum >= m {
            c := r - l + 1
            if z > c {
                z = c
            }
            sum -= a[l]
            l++
        }
    }
    if z > n {
        fmt.Println(-1)
    } else {
        fmt.Println(z)
    }
}

これで計算量もぐっと減ってきれいに実装できました。

ただ、完全にしゃくとり法を理解できたというわけじゃないので、そこだけが少し心残りです。。

ではまた👍