[백준][python] 11659번: 구간 합 구하기 4
11659번: 구간 합 구하기 4
문제
수 N개가 주어졌을 때, i번째 수부터 j번째 수까지 합을 구하는 프로그램을 작성하시오.
입력 조건
첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다.
둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다.
셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j가 주어진다.
- 1 ≤ N ≤ 100,000
- 1 ≤ M ≤ 100,000
- 1 ≤ i ≤ j ≤ N
출력 조건
총 M개의 줄에 입력으로 주어진 i번째 수부터 j번째 수까지 합을 출력한다.
첫 번째 시도 .
n,m = map(int,input().split())
num = list(map(int,input().split()))
for _ in range(m):
sum=0
i,j=map(int,input().split())
for k in range(i,j+1):
sum+=num[k-1]
print(sum)
»intput
5 3
5 4 3 2 1
1 3
2 4
5 5
»output(시간초과)
12
9
1
(Time Error)
fail
🌝 Thinking
특정 구간의 부분합을 구하기 위해 단순히 특정구간을 찾아 슬라이싱하여 합을 하면
모두 시간 초과가 나왔다.
많은 제출을 했는데,,, 다 슬라이싱 방법만 바꿨을 뿐 시간 복잡도는 O($N^2$) 를 벗어나지 못했다.
여러가지 고민 끝에…
부분합 미리 구하고 호출을 하면 어떨까 ?!
두 번째 시도 .
import sys
input = sys.stdin.readline
n,m = map(int,input().split())
num = list(map(int,input().split()))
d=[0]*(n+1)
d[0]=num[0]
for i in range(1,n):
d[i] = d[i-1] + num[i]
for k in range(m):
i,j=map(int,input().split())
print(d[j-1]-d[i-2])
»intput
5 3
5 4 3 2 1
1 3
2 4
5 5
»output
12
9
1
success
🌝 Thinking
부분합을 미리 구하였다.
다이나믹 프로그래밍 Bottom Up 방식으로 DP테이블에 index+1까지의 수의 합을 넣어주었다.
우리가 만약 3 ~ 6번까지의 합을 구하고싶으면,
d[6] - d[2]를 계산해주면 되는 것이었다.
이러면 시간 복잡도가 현저히 줄어들게 된다. 시간복잡도 O(N)
💡 깨달은 점.
- 내가 사용한 이 방식이 prefix_sum이라는 구간합 알고리즘이 있었고, 이 외에도 투 포인터알고리즘을 이용하여 해결 할 수도 있다.
댓글남기기