2023. 2. 13. 19:42ㆍ개발/👾 PS
구간 합 알고리즘
1) 구간 합 알고리즘 : 합 배열을 통해 기존 리스트의 일정 범위의 합을 구하는 알고리즘
* 시간 복잡도 : O(1)
2) 구현
(1) 합 배열 만들기
합 배열 : 기존 리스트 0 ~ i 번까지의 합
S[i] = S[i-1] + A[i]
인덱스 | 0 | 1 | 2 | 3 | 4 |
리스트 A | 1 | 2 | 3 | 4 | 5 |
합 배열 S | 1 | 3 | 6 | 10 | 15 |
(2) 구간 합 구하기
구간 합 : 기존 리스트 a ~ b 번까지의 합
prefixSum = S[b] - S[a-1]
인덱스 | 0 | 1 | 2 | 3 | 4 |
리스트 A | 1 | 2 | 3 | 4 | 5 |
합 배열 S | 1 | 3 | 6 | 10 | 15 |
리스트 A의 인덱스 1번 ~ 3번까지의 구간 합은
A[1] + A[2] + A[3] = (A[0] + A[1] + A[2] + A[3]) - (A[0]) = S[3] - S[0]
-> S[3] - S[0] 으로 구하면 된다
3) 문제 풀이
# 1 구간 합 구하기 1 - 백준 11659번
일차원 구간 합
https://www.acmicpc.net/problem/11659
11659번: 구간 합 구하기 4
첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j
www.acmicpc.net
N,M = map(int,input().split())
num = list(map(int, input().split()))
# 합 배열 생성
sumList = []
sum = 0
for a in range(N):
sum+=num[a]
sumList.append(sum)
# 구간 합
p_sumList = []
for k in range(M):
# i,j : 범위
i, j = map(int, input().split())
if i == 1:
p_sumList.append(sumList[j-1])
else:
p_sumList.append(sumList[j-1] - sumList[i-2])
for b in range(len(p_sumList)):
print(p_sumList[b])
# 2 구간 합 구하기 2 - 백준 11660번
이차원 구간 합
https://www.acmicpc.net/problem/11660
11660번: 구간 합 구하기 5
첫째 줄에 표의 크기 N과 합을 구해야 하는 횟수 M이 주어진다. (1 ≤ N ≤ 1024, 1 ≤ M ≤ 100,000) 둘째 줄부터 N개의 줄에는 표에 채워져 있는 수가 1행부터 차례대로 주어진다. 다음 M개의 줄에는 네
www.acmicpc.net
import sys
input = sys.stdin.readline
n, m = map(int,input().split())
# A : 데이터 리스트 -> 리스트의 인덱스는 0부터 시작하기 때문에 헷갈리지 않기 위해 (n+1)칸 만듦
A = [[0] * (n+1)]
for i in range(n):
A_row = [0]+[int(x) for x in input().split()]
A.append(A_row)
# D : 합 배열 -> 리스트의 인덱스는 0부터 시작하기 때문에 헷갈리지 않기 위해 (n+1)칸씩 만듦
D = [[0] * (n+1) for _ in range(n+1)]
for i in range(1,n+1):
for j in range(1,n+1):
D[i][j] = D[i][j-1] + D[i-1][j] - D[i-1][j-1] + A[i][j]
for _ in range(m):
x1, y1, x2, y2 = map(int,input().split())
result = D[x2][y2] - D[x1-1][y2] -D[x2][y1-1]+D[x1-1][y1-1]
print(result)
+) 2023.03.04 알고리즘 스터디에서
# 3 나머지 합 - 백준 10986번
https://www.acmicpc.net/problem/10986
10986번: 나머지 합
수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오. 즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j)
www.acmicpc.net
n,m = map(int,input().split())
num = list(map(int, input().split()))
ps = [0]
left = []
sum = 0
zero = 0
sameNum = [0]*(m+1)
sN = 0
# 합 배열 생성
for i in num:
sum += i
ps.append(sum)
# 나머지 배열 생성
for j in ps:
leftover = j % m
left.append(leftover)
# 나머지 배열에서 '요소의 값'이 0인 것의 개수
if leftover == 0:
zero+=1
# 나머지 배열에서 같은 값의 개수 저장
if leftover > 0:
sameNum[leftover] += 1
# 같은 값 2개 선택하는 경우 - 나머지 배열에서 같은 값의 개수가 1보다 크면 조합 사용
for k in sameNum:
if k > 1:
sN += k*(k-1) / 2
# 0의 개수
sN += zero-1
# 0 2개를 선택하는 경우 - 조합 사용
sN += (zero-1)*(zero-2) / 2
print(int(sN))
'개발 > 👾 PS' 카테고리의 다른 글
[슬라이딩 윈도우] 알고리즘 (2) | 2023.03.15 |
---|---|
[투 포인터] 자료구조 (0) | 2023.03.10 |
[ DFS, BFS ] 완전 탐색 알고리즘 (0) | 2023.02.05 |
알고리즘 기본 개념 (0) | 2023.02.05 |
1월 2주차 코딩일지 (1) | 2023.01.21 |