𝘚𝘭𝘰𝘸 𝘣𝘢𝘡 𝘴𝘡𝘦𝘒π˜₯𝘺

[μ•Œκ³ λ¦¬μ¦˜] λˆ„μ  ν•©(prefix sum) λ³Έλ¬Έ

μ•Œκ³ λ¦¬μ¦˜

[μ•Œκ³ λ¦¬μ¦˜] λˆ„μ  ν•©(prefix sum)

.23 2024. 11. 9. 13:11

1. λˆ„μ  ν•©(prefix sum)

1.1 κ°œλ…

νŠΉμ • λ°°μ—΄μ—μ„œ μ–΄λ– ν•œ κ΅¬κ°„κΉŒμ§€μ˜ 합을 κ΅¬ν•˜λŠ” 방식. μ–΄λ– ν•œ 1차원 λ°°μ—΄ [ 1, 5, 2, 10, 1, 8 ] μ—μ„œ κ°€μž₯ 합이 큰 길이가 3인 λΆ€λΆ„ 배열을 κ³ λ₯Ό λ•Œ, [ 1, 5, 2 ], [ 5, 2, 10 ], ... , [ 10, 1, 8 ] 을 ν•˜λ‚˜ν•˜λ‚˜μ”© λ°˜λ³΅λ¬Έμ„ λŒλ €λ‚˜κ°€λ©΄μ„œ 비ꡐ해 λ‚˜κ°€λŠ” 것이 μ•„λ‹ˆλΌ 미리 λˆ„μ ν•©μ„ 계산해둔 λ°°μ—΄ [ 1, 6, 8, 18, 19, 27 ] λ₯Ό ν™œμš©ν•˜μ—¬ 계산을 ν•˜κΈ° λ•Œλ¬Έμ—, κ³„μ‚°λŸ‰μ—μ„œ 큰 이득이 μžˆλ‹€.

 

1.2 1차원 λ°°μ—΄

μ•Œκ³ λ¦¬μ¦˜ μž‘λ™ 방식은 λ‹€μŒκ³Ό κ°™λ‹€.

 

1. 길이가 N(λ˜λŠ” N + 1)의 λˆ„μ ν•© 배열을 μ„ μ–Έν•˜κ³ , 각 λˆ„μ ν•© λ°°μ—΄μ˜ i번째 μΈλ±μŠ€μ—λŠ” 원본 λ°°μ—΄μ˜ 1λ²ˆμ§ΈλΆ€ν„° i번째 μ›μ†Œμ˜ 합을 μ €μž₯ν•œλ‹€.

2. a번째 μ›μ†ŒλΆ€ν„° b번째 μ›μ†Œ(1 ≀ a ≀ b ≀ N)κΉŒμ§€μ˜ λˆ„μ ν•©μ„ κ΅¬ν•˜κ³  싢을 λ•Œ, κ΅¬ν•˜λŠ” 방식은

    b번째 λˆ„μ ν•© κ°’μ—μ„œ (a - 1)번째 λˆ„μ ν•© 값을 λΉΌμ„œ κ΅¬ν•œλ‹€.

 

 

그림의 μ˜ˆμ‹œμ™€ 같은 λ°°μ—΄μ—μ„œ

3번째 μ›μ†Œ(6)μ—μ„œ 6번째 μ›μ†Œ(1)κΉŒμ§€μ˜ λˆ„μ ν•©μ„ κ΅¬ν•˜λŠ” 방법은

prefix_sum[5] - prefix_sum[1] = 23 - 6 = 17

 

 

[a]λΆ€ν„° [b]κΉŒμ§€μ˜ 합은 1 ~ bκΉŒμ§€μ˜ ν•©μ—μ„œ κ²ΉμΉ˜λŠ” 뢀뢄인 1 ~ (a-1) 을 λΉΌμ£Όλ©΄ 되기 λ•Œλ¬Έμ—,

미리 μ •μ˜λœ λ°°μ—΄λ§Œ 있으면 O(1)λ§Œμ— 계산이 κ°€λŠ₯ν•œ κ°„λ‹¨ν•œ μ›λ¦¬μ˜ μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

 

1.2.1 μ½”λ“œ

int N, a, b; // predefined

vector<int> A(N); // predefined
vector<int> prefix_sum(N + 1, 0);

for(int i = 1; i <= N; i++) {
	prefix_sum[i] = prefix_sum[i - 1] + A[i - 1];
}

// a ~ bκΉŒμ§€ ꡬ간합
sum = prefix_sum[b + 1] - prefix_sum[a];

 

 

1.3 2차원 λ°°μ—΄

사싀 이 ν¬μŠ€νŒ…μ„ ν•˜κ²Œ 된건 2차원 λ°°μ—΄μ˜ λˆ„μ ν•© λ•Œλ¬Έμ—...

 

2차원 λ°°μ—΄μ—μ„œμ˜ λˆ„μ ν•©μ€ 1차원 λ°°μ—΄μ—μ„œμ˜ 원리와 λ™μΌν•˜λ‹€.

λ‹€λ§Œ, λˆ„μ ν•© 배열을 λ§Œλ“€μ–΄μ£ΌλŠ” λ°©μ‹μ—μ„œλΆ€ν„° 쑰금 생각을 ν•΄μ€˜μ•Ό ν•œλ‹€.

 

 

2차원 λ°°μ—΄μ˜ λˆ„μ ν•© 배열을 λ§Œλ“€μ–΄ μ€„λ•ŒλŠ” (0, 0) ~ (i, j) κΉŒμ§€μ˜ μ§μ‚¬κ°ν˜• λ°°μ—΄ λ‚΄ λˆ„μ ν•©μ„ κ΅¬ν•΄μ€€λ‹€λŠ” μƒκ°μœΌλ‘œ 계산을 ν•΄μ£Όλ©΄ λœλ‹€.

(0, 0) ~ (i, j)κΉŒμ§€μ˜ λˆ„μ ν•©μ€ λ‹€μŒκ³Ό 같이 κ΅¬ν•œλ‹€.

 

[ (0, 0) ~ (i, j - 1)κΉŒμ§€μ˜ λˆ„μ ν•© + (0, 0) ~ (i - 1, j)κΉŒμ§€μ˜ λˆ„μ ν•© + (i, j)의 λ°°μ—΄κ°’ ] - [ (0, 0) ~ (i - 1, j - 1)κΉŒμ§€μ˜ λˆ„μ ν•© ]

 

그리고 (a, b) ~ (c, d) μ‚¬μ΄μ˜ λˆ„μ ν•©μ€ λ‹€μŒκ³Ό 같이 κ΅¬ν•œλ‹€.

 

[ (c, d)κΉŒμ§€μ˜ λˆ„μ ν•© + (a - 1, b - 1)κΉŒμ§€μ˜ λˆ„μ ν•© ] - [ (a - 1, d)κΉŒμ§€μ˜ λˆ„μ ν•© + (c, b - 1)κΉŒμ§€μ˜ λˆ„μ ν•©) ]

 

 

λ‹€μŒκ³Ό 같이 0κ³Ό 1둜 이루어진 λ°°μ—΄ A[][]κ°€ μžˆλ‹€κ³  ν•  λ•Œ, (3, 2)κΉŒμ§€μ˜ λˆ„μ ν•©μ€ 3이 λœλ‹€.

 

λˆ„μ ν•© λ°°μ—΄μ—μ„œ (3, 2)λ₯Ό μ΄λ£¨λŠ” 값은 λ‹€μŒκ³Ό 같이 κ΅¬ν•œλ‹€.

 

 

1️⃣ (0, 0) ~ (3, 1) κΉŒμ§€μ˜ λˆ„μ ν•©

 + 2️⃣ (0, 0) ~ (2, 2) κΉŒμ§€μ˜ λˆ„μ ν•©

+ 3️⃣ (3, 2)μ—μ„œμ˜ λ°°μ—΄ κ°’(μ—¬κΈ°μ„œλŠ” 0)

- 4️⃣ κ²ΉμΉ˜λŠ” ꡬ간((0, 0) ~ (2, 1) κΉŒμ§€μ˜ λˆ„μ ν•©)

을 λͺ¨λ‘ 계산해주면 1️⃣ 2 + 2️⃣ 2 + 3️⃣ 0 - 4️⃣ 1 = 3 이 λœλ‹€.

 

이런 μ‹μœΌλ‘œ λˆ„μ ν•© 배열을 λͺ¨λ‘ 계산해주면 λ‹€μŒκ³Ό κ°™λ‹€. (μ •μ‹ μ—†μŒ)

 

 

 

그럼 μ—¬κΈ°μ„œ (a, b) ~ (c, d) κΉŒμ§€μ˜ λˆ„μ ν•©μ„ κ΅¬ν•˜λŠ” 방식은 μ•žμ„  방식과 λ§ˆμ°¬κ°€μ§€λ‘œ λ‹€μŒκ³Ό 같이 κ΅¬ν•œλ‹€.

(3, 1) ~ (6, 5) κΉŒμ§€μ˜ λˆ„μ ν•©μ΄ κΆκΈˆν•  λ•Œ, 

 

 

 

1️⃣ (0, 0) ~ (6, 5) κΉŒμ§€μ˜ λˆ„μ ν•©

 + 2️⃣ λ‘λ²ˆ λΉΌμ§€λŠ” ꡬ간((0, 0) ~ (2, 0) κΉŒμ§€μ˜ λˆ„μ ν•©)

- 3️⃣ (0, 0) ~ (2, 5) κΉŒμ§€μ˜ λˆ„μ ν•©

- 4️⃣ (0, 0) ~ (6, 0) κΉŒμ§€μ˜ λˆ„μ ν•©

을 λͺ¨λ‘ 계산해주면 1️⃣ 5 + 2️⃣ 0 - 3️⃣ 2 - 4️⃣ 0 = 3 μ΄ λœλ‹€.

 

 

1.3.1 μ½”λ“œ

int N, a, b, c, d; // predefined

vector<vector<int>> A(N, vector<int>(N)); // predefined
vector<vector<int>> prefix_sum(N, vector<int>(N + 1, 0));

for(int i = 1; i <= N; i++)
	for(int j = 1; j <= N; j++)
    	prefix_sum[i][j] = A[i - 1][j - 1] + prefix_sum[i][j - 1]
			+ prefix_sum[i - 1][j] - prefix_sum[i - 1][j - 1];

sum = prefix_sum[c + 1][d + 1] - prefix_sum[a][d]
 		- prefix_sum[c][b] + prefix_sum[a][b]

 

λˆ„μ  ν•© μ‚¬μš©ν•΄μ„œ ν’€μ–΄μ•Όν–ˆλ˜ 문제

πŸ”— ꡬ름-놀이곡원

Comments