ํ์คํ ์น๐ ๊ฐ๋ฐ์ ์ง๋ง์ ๐ง๐ฝโ๐ป
โ ์ธ๊ณต์ง๋ฅ ๊ด์ฌ ๐ค
Categories
-
โฃ
โถ COMPUTER_SCIENCE
๐: 7 -
โฃ
โถ WEB
๐: 3 -
โฃ
โถ ETC
๐: 3-
โ
โฃ
ETCS
๐: 10 -
โ
โฃ
SUBBRAIN ๊ฐ๋ฐ๊ธฐ
๐: 5 -
โ
โ
YOS ๊ฐ๋ฐ๊ธฐ
๐: 1
-
โ
โฃ
-
โ
โถ AI
๐: 9-
โฃ
AITOOLS
๐: 3 -
โฃ
CV
๐: 2 -
โฃ
DEEP_LEARNING
๐: 1 -
โฃ
DATA_VIS
๐: 2 -
โฃ
GRAPH
๐: 1 -
โฃ
LIGHTWEIGHT
๐: 1 -
โฃ
MATH
๐: 1 -
โฃ
NLP
๐: 3 -
โ
STRUCTURED_DATA
๐: 2
-
โฃ
Python for Algorithms-Tree
Python for Algorithms-Tree
๋น์ ํ ๊ตฌ์กฐ, ์์๋ค ๊ฐ์ 1:n, ๊ณ์ธตํ ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ค.
์ํธ ๋ฐฐํ ์งํฉ
์๋ก์ ์งํฉ(disjoint set) ํน์ ์ํธ ๋ฐฐํ ์งํฉ์ ์งํฉ ๊ฐ์ ์ค๋ณต๋๋(๊ต์งํฉ) ์์๊ฐ ์๋ ์งํฉ๋ค์ด๋ค.
๋ฌธ์ ๋ฅผ ํ ๋ ์๋ก ๊ต์งํฉ์ด ์๋ ์งํฉ๋ค์ ์ ๋ฑ์ด ์ฃผ์ ๋ผ๋ฉด ์๊ฐํด๋ณผ ๋ง ํ๋ค.
์งํฉ์ ๋ํ์(๋ฃจํธ)๋ก ๊ฐ ์งํฉ์ ๊ตฌ๋ถํ๋ค.
p = [i for i in range(node_num)] # p[x]: ๋
ธ๋ x์ ๋ถ๋ชจ ์ ์ฅ
rank = [i for i in range(node_num)] # rank[x]: ๋ฃจํธ ๋
ธ๋๊ฐ x์ธ ํธ๋ฆฌ์ ๋ญํฌ ๊ฐ ์ ์ฅ
def make_set(x):
"""์ ์ผํ ๋ฉค๋ฒ X๋ฅผ ํฌํจํ๋ ์๋ก์ด ์งํฉ์ ์์ฑํ๋ ์ฐ์ฐ"""
p[x] = x # ์๊ธฐ์์ ์ด ๋ฃจํธ
rank[x] = 0
def find_set(x):
""" x๋ฅผ ํฌํจํ๋ ์งํฉ์ ์ฐพ๋ ์คํผ๋ ์ด์
"""
if x != p[x]: # x๊ฐ ๋ฃจํธ๊ฐ ์๋ ๊ฒฝ์ฐ
# Path Compression: ํน์ ๋
ธ๋์์ ๋ฃจํธ๊น์ง์ ๊ฒฝ๋ก์ ์กด์ฌํ๋ ๋
ธ๋๊ฐ ๋ฃจํธ๋ฅผ ๋ถ๋ชจ๋ก ๊ฐ๋ฆฌํค๋๋ก ๊ฐฑ์ , ๋จ๋ฐฉํฅ ๊ทธ๋ํ์์๋ง ๊ฐ๋ฅํจ
p[x] = find_set(p[x]) # ์๋ฐฉํฅ์ผ ์ ๋ค์์ผ๋ก ๋์ฒด : return find_set(x)
return p[x]
def union(x, y):
""" x์ y๋ฅผ ํฌํจํ๋ ๋ ์งํฉ์ ํตํฉํ๋ ์คํผ๋ ์ด์
"""
link(find_set(x), find_set(y))
def link(x, y):
""" ๋ ๋ฃจํธ๋ฅผ ํตํฉํ๋ ์คํผ๋ ์ด์
"""
if rank[x] > rank[y]:
p[y] = x
else:
p[x] = y
if rank[x] == rank[y]:
rank[y] += 1
์ด์ง ํ์ ํธ๋ฆฌ
์ด์ง ํธ๋ฆฌ๋ ๋ชจ๋ ๋ ธ๋๋ค์ด 2๊ฐ์ ์๋ธํธ๋ฆฌ๋ฅผ ๊ฐ๋ ํน๋ณํ ํํ
๋ ๋ฒจ์ด $i$๋ผ๋ฉด ๋ ธ๋์ ์ต๋ ๊ฐฏ์๋ $2^i$๊ฐ
์ด์ง ํ์ ํธ๋ฆฌ๋ ํ์ ์์ ์ ํจ์จ์ ์ผ๋ก ํ๊ธฐ ์ํ ์๋ฃ ๊ตฌ์กฐ, ๋ค์๊ณผ ๊ฐ์ ํน์ฑ์ ๊ฐ์ง
- ๊ฐ ๋ ธ๋๋ ์๋ก ๋ค๋ฅธ ์ ์ผํ ํค(๋ฐ์ดํฐ)๋ฅผ ๊ฐ์ง๋ค.
- $์ผ์ชฝ\ ์์\ ๊ฐ <= ์์ ์\ ๊ฐ <= ์ค๋ฅธ์ชฝ\ ์์\ ๊ฐ$
- ํธ๋ฆฌ๋ฅผ ์ค์ ์ํ ์ ์ค๋ฆ์ฐจ ์ ์ ๋ ฌ์ ์ป์ ์ ์๋ค.
AVL ํธ๋ฆฌ
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ (segment tree)
์์ด์ ์ด ํฉ, ์ด ๊ณฑ, ์ต๋๊ฐ, ์ต์๊ฐ ๋ฑ์ $O(\log N)$์ ์๊ฐ์ ํด๊ฒฐํ ์ ์๋ ์๋ฃ๊ตฌ์กฐ
import math
def create_seg_tree(num_list):
tree = [0] * (1 << (math.ceil(math.log2(len(num_list)))+1))
# ํ์ํ ๋
ธ๋ ์ == ์์ ๋
ธ๋(N) + ๋ถ๋ชจ ๋
ธ๋(N-1) == 2N - 1
# ๋ฐ๋ผ์ ๋์ด๋ฅผ H๋ผ๊ณ ๋์ ๋ โ^{H}_{n=0}2^n >= 2N -1์ ๋ง์กฑํด์ผ ํ๋ค.
# tree์ ํฌ๊ธฐ๋ 2์ (์์ ํธ๋ฆฌ์ ๋์ด + 1)์น์ด๋ฉด ์ ๋ ๋ถ์กฑํ์ง ์๋ค.
def create_recursive(start, end, index=1):
'''
์ฌ๊ท๋ฅผ ํตํ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ ์์ฑ
index: ์ฒ๋ฆฌ ์ค์ธ ๋
ธ๋
- index *2, index * 2 + 1 : ๋
ธ๋์ ์์ ๋
ธ๋๋ค
- ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ์ต๊ณ ๋ถ๋ชจ์ธ 1๋ถํฐ ์์, ์์์ ๊ฐ๋ฅดํค๋ ๋ฐฉํฅ์ผ๋ก ์งํํจ
start - mid : ์ผ์ชฝ ์์์ด ์ ์ฅํ๋ ๊ฐ
mid+1 - end : ์ค๋ฅธ์ชฝ ์์์ด ์ ์ฅํ๋ ๊ฐ
'''
nonlocal tree
# tree์ leap์ ๋๋ฌํ์ผ๋ฉด num_list ๊ฐ ๊ทธ๋๋ก ์ฝ์
if start == end:
tree[index] = num_list[start]
return tree[index]
mid = (start + end) // 2
# ์ข์ธก ๋
ธ๋์ ์ฐ์ธก ๋
ธ๋ ๊ฐ์ ๊ตฌํด ๋ถ๋ชจ ๋
ธ๋์ ๊ฐ์ ํฉ์ณ ๋ง๋ ๋ค. (์ด๋ ํฉ์ด ์๋๋ผ ๊ตฌ๊ฐ๊ณฑ์ด๋ฉด ๋ฐ๊ฟ์ฃผ์)
tree[index] = create_recursive(
start, mid, index * 2) + create_recursive(mid + 1, end, index * 2 + 1)
return tree[index]
create_recursive(0, len(num_list)-1)
return tree
def interval_sum(tree, left, right, numCount):
def sum_recursive(start, end, index=1):
'''
์ฌ๊ท๋ฅผ ํตํ ๊ตฌ๊ฐํฉ ๊ณ์ฐ ํจ์
index: ํ์ฌ ์ฒ๋ฆฌ ์ค์ธ ์ธ๋ฑ์ค
start - end : ํ์ฌ index ๋
ธ๋๊ฐ ๊ฐ์ ์ ์ฅํ ๊ตฌ๊ฐ
left, right : ๊ตฌ๊ฐ ํฉ์ ๊ตฌํ๊ณ ์ ํ๋ ๋ฒ์
'''
nonlocal tree, left, right
# ์ํ๋ ๊ตฌ๊ฐ์ด tree ๋ฐ์ธ ๊ฒฝ์ฐ
if left > end or right < start:
return 0 # ๊ณฑ์ผ ๊ฒฝ์ฐ ํญ๋ฑ์์ธ 1
# ํ์ฌ ์ธ๋ฑ์ค๊ฐ ํฌํจํ๋ ๊ตฌ๊ฐ์ด ์ ๋ถ ๋ด๊ฐ ์ํ๋ ๊ตฌ๊ฐ ์์ ์๋ ๊ฒฝ์ฐ ๋ํ๋ค.
if left <= start and right >= end:
return tree[index]
# ์ผ๋ถ๋ง ๊ฒน์น ๊ฒฝ์ฐ๋ ๋ ์์์ผ๋ก ๋๋์ด ๊ตฌ๊ฐ ๋ด์ ์๋ ์์๋ง ๋ํจ
mid = (start + end) // 2
return sum_recursive(start, mid, index * 2) + sum_recursive(mid + 1, end, index * 2 + 1)
return sum_recursive(0, numCount-1)
def update(tree, where, diff, numCount):
def update_recursive(start, end, index=1):
'''
ํน์ ์์์ ๊ฐ์ ์์ ํ๋ ํจ์
index : ํ์ฌ ์์ ํ์ ์ฌ๋ถ๋ฅผ ํ๋จํ๊ณ ์๋ ํจ์
start - end: index ๋
ธ๋๊ฐ ํฌํจํ๊ณ ์๋ ๋ฒ์
where : ๊ตฌ๊ฐ ํฉ์ ์์ ํ๊ณ ์ ํ๋ ๋
ธ๋
value : ์์ ํ ๊ฐ
'''
nonlocal tree, where, diff
# ๋ฒ์ ๋ฐ์ ์๋ ๊ฒฝ์ฐ๋ ์๋ฌด๊ฒ๋ ์ํ๊ณ ์ฌ๊ท ์ค๋จ
if where < start or where > end:
return
# ๋ฒ์ ์์ ์์ผ๋ฉด ๋ด๋ ค๊ฐ๋ฉด์ ๋ค๋ฅธ ์์๋ ๊ฐฑ์
tree[index] += diff
if start != end:
mid = (start + end) // 2
update_recursive(start, mid, index*2)
update_recursive(mid + 1, end, index*2+1)
update_recursive(0, numCount-1)
return tree
# segment tree
{: #segment-tree}
numCount, changeCount, caseCount = map(int, input().split())
num_list = [0 for _ in range(numCount)]
for i in range(numCount):
num_list[i] = int(input())
seg = create_seg_tree(num_list)
for j in range(changeCount + caseCount):
cmd, par1, par2 = map(int, input().split())
if cmd == 1:
loc, val = par1-1, par2
seg = update(seg, loc, val - num_list[loc], numCount)
elif cmd == 2:
fr, to = par1-1, par2-1
print(interval_sum(seg, fr, to, numCount))
์๋๋ ๋ค๋ฅธ ๋ฒ์ ์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ด๋ค.
+ PROS
- ๋ฐ๋ณต๋ฌธ๊ณผ ๋นํธ ์ฐ์ฐ์ ํ์ฉํด ์ข ๋ ๋น ๋ฅด๋ค.
- ์๋ฃํ์ ํฌ๊ธฐ๊ฐ ์
๋ ฅ ๊ฐ์ 2๋ฐฐ๋ก, ๋น๊ต์ ํจ์จ์ ์ด๋ค.
- ์๋ฃํ์ ๋ฐฐ์น๋ ์์๋ค์ด ์์น์ ์ผ๋ก ์ง๊ด์ ์.
- ์์น n์ $n\times 2,\ n\times 2 + 1$์ด ์์์ด๋ฉฐ, ๋ฐ๋๋ก $n//2$๋ ๋ถ๋ชจ
- ์์๋ค์ด ์ธต ๋ณ๋ก ์ผ๋ ฌ๋ก ๋ฐฐ์น๋จ.
- CONS
- ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ํ๋ค๋ค. ํนํ, left ์ธ๋ฑ์ค์ right ์ธ๋ฑ์ค์ ํ์ฉ ๋ถ๋ถ
- ์๋ฃํ์ ๋ฐฐ์น๋ ์์๋ค์ด ์ค์ ์๋ฆฌ์ ๋
ธ๋์ ์กฐ๊ธ ๋ค๋ฅด๋ค.
- ์๋ฅผ ๋ค์ด, ์์์ ๊ฐฏ์๊ฐ ํ์ ์ผ ๊ฒฝ์ฐ, ์๋ก ๋ค๋ฅธ ์ธต ๊ฐ์ ํฉ์ ๊ฐ์ง๊ณ ์๋ ๋ถ๋ชจ ๋
ธ๋๊ฐ ์๊น.
- ๋ฐ๋ผ์ lazy propagation ๊ตฌํ์ด ํ๋ค๊ณ ๊ตฌํํ์ง ์์ ์, ๊ตฌ๊ฐ ์
๋ฐ์ดํธ์ ์ฑ๋ฅ์ด ๋จ์ด์ง๋ค.
# ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ ์์ฑ
{: #๋ฐ๋ณต๋ฌธ์-์ด์ฉํ-์ธ๊ทธ๋จผํธ-ํธ๋ฆฌ-์์ฑ}
def create_tree(num_list):
# ๋ถ๋ชจ ๋
ธ๋๋ค์ด ๋ค์ด๊ฐ ๊ณต๊ฐ + ์๋ณธ ๊ฐ ๊ณต๊ฐ
tree = [0 for _ in range(len(num_list))] + num_list # ํญ๋ฑ์ ์ฑ์ฐ๊ธฐ
# ๋ถ๋ชจ ๋
ธ๋ ์์ฑ
for i in range(len(num_list) - 1, 0, -1): # ๊ฑฐ๊พธ๋ก ์์ํ์ฌ ๋ง๋จ ๋
ธ๋์ ๊ฐ๊น์ด ๋ถ๋ชจ๋ถํฐ ์์ฑ
tree[i] = tree[i << 1]+tree[i << 1 | 1] # ์ฐ์ฐ ๋ฃ๊ธฐ
return tree
# ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํ ๊ตฌ๊ฐํฉ ๊ตฌํ๊ธฐ
{: #๋ฐ๋ณต๋ฌธ์-์ด์ฉํ-๊ตฌ๊ฐํฉ-๊ตฌํ๊ธฐ}
def interval_total(num_count, tree, left, right):
# ์ค์ ๋ฒ์๋ ๋ถ๋ชจ ๊ณต๊ฐ์ ์ํด ๋ฐ๋ ค๋ฌ์ผ๋ฏ๋ก ๊ทธ๋งํผ ๋ํด์ค
left += num_count
right += num_count
result = 0 # ํญ๋ฑ์
while (left <= right):
# ์ธ๋ฑ์ค์ ํ์ ์ง์ ์ฌ๋ถ์ ๋ฐ๋ผ ๋๊ฐ์ง๋ก ๋๋๋ค.
# 1. ์ด ๋
ธ๋์ ๊ฐ์ ํฌํจํ ๋ถ๋ชจ ๋
ธ๋๊ฐ ์์(=๋ํ์ง ์์)
# 2. ์ด ๋
ธ๋์ ๊ฐ์ ํฌํจํ ๋
ธ๋๊ฐ ์์ (=๋ํด์ค์ผ ํจ)
if (left & 1): # ์ผ์ชฝ ์ธ๋ฑ์ค๊ฐ ํ์์ด๋ฉด
result += tree[left] # ํด๋น ๊ฐ์ ์ฐ์ฐ
left += 1 # ์ธ๋ฑ์ค ์ฆ๊ฐ
if not (right & 1): # ์ค๋ฅธ์ชฝ ์ธ๋ฑ์ค๊ฐ ์ง์์ด๋ฉด
result += tree[right] # ํด๋น ๊ฐ์ ์ฐ์ฐ
right -= 1 # ์ธ๋ฑ์ค ๊ฐ
# ์ธ๋ฑ์ค๋ฅผ ์ ๋ฐ์ผ๋ก ์ค์ == ํด๋น ๊ฐ์ ๋ถ๋ชจ ๋
ธ๋๋ก
left >>= 1
right >>= 1
return result
# ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํ ํธ๋ฆฌ ๊ฐฑ์
{: #๋ฐ๋ณต๋ฌธ์-์ด์ฉํ-ํธ๋ฆฌ-๊ฐฑ์ }
def update(tree, index, val, num_count):
index += num_count
tree[index] = val
# ๋ถ๋ชจ ๋
ธ๋ ์
๋ฐ์ดํธ
while index > 1:
tree[index >> 1] = tree[index] + tree[index ^ 1] # ์ฐ์ฐ
index >>= 1
return tree
# segment tree
{: #segment-tree}
numCount, changeCount, caseCount = map(int, input().split())
arr = [0 for _ in range(numCount)]
for i in range(numCount):
arr[i] = int(input())
seg = create_tree(arr)
for j in range(changeCount + caseCount):
cmd, par1, par2 = map(int, input().split())
if cmd == 1:
loc, val = par1-1, par2
update(seg, loc, val, numCount)
elif cmd == 2:
fr, to = par1-1, par2-1
print(interval_total(numCount, seg, fr, to))
class SegmentTree {
private long[] tree;
private int n;
public SegmentTree(long[] nums) {
n = nums.length;
tree = new long[4 * n]; // use 4 * n for a balanced tree
buildTree(nums, 1, 0, n - 1);
}
// builds the segment tree recursively
private void buildTree(long[] nums, int node, int start, int end) {
if (start == end) {
tree[node] = nums[start];
} else {
int mid = (start + end) / 2;
int leftChild = 2 * node, rightChild = 2 * node + 1;
buildTree(nums, leftChild, start, mid);
buildTree(nums, rightChild, mid + 1, end);
// combine the results of the left and right subtrees
tree[node] = tree[leftChild] + tree[rightChild];
}
}
// updates the value at index i to val
public void update(int i, long val) {
updateTree(1, 0, n - 1, i, val);
}
// updates the segment tree recursively
private void updateTree(int node, int start, int end, int i, long val) {
if (start == end) {
tree[node] = val;
} else {
int mid = (start + end) / 2;
int leftChild = 2 * node, rightChild = 2 * node + 1;
if (i <= mid) {
updateTree(leftChild, start, mid, i, val);
} else {
updateTree(rightChild, mid + 1, end, i, val);
}
// combine the results of the left and right subtrees
tree[node] = tree[leftChild] + tree[rightChild];
}
}
// returns the sum of the values in the range [i, j]
public long sumRange(int i, int j) {
return queryTree(1, 0, n - 1, i, j);
}
// queries the segment tree recursively
private long queryTree(int node, int start, int end, int i, int j) {
if (j < start || i > end) {
return 0;
} else if (i <= start && j >= end) {
return tree[node];
} else {
int mid = (start + end) / 2;
int leftChild = 2 * node, rightChild = 2 * node + 1;
return queryTree(leftChild, start, mid, i, j) + queryTree(rightChild, mid + 1, end, i, j);
}
}
}
๋์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ(Dynamic segment tree)
์ง์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ(Persistent segment tree)
๋ค์ฐจ์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ (multi dimensional segment tree)
๊ฒ์ผ๋ฅธ ์ ํ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ (segment tree with lazy propagation)
- ํ๋จ ์ฝ๋๋ ์ดํด๋ฅผ ๋๊ธฐ ์ํด
dictionary
๋ฅผ ํ์ฉํ์ผ๋ฉฐ, ์ค์ ๋ก ์๋ ์ฝ๋๋ ํ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ด๋ง์ด๋งํ๋ฏ๋ก, ๋ค์ฐจ์ ๋ฐฐ์ด์ด๋lazy
์value
๋ฅผ ๋ค๋ฅธ ๋ฐฐ์ด๋ก ๋๋์.
import sys
import math
input = sys.stdin.readline
def createSegTreeLazy(nums):
# ํ์ํ ๋
ธ๋ ์ == ์์ ๋
ธ๋(N) + ๋ถ๋ชจ ๋
ธ๋(N-1) == 2N - 1
# ๋ฐ๋ผ์ ๋์ด๋ฅผ H๋ผ๊ณ ๋์ ๋ โ^{H}_{n=0}2^n >= 2N -1์ ๋ง์กฑํด์ผ ํ๋ค.
# tree์ ํฌ๊ธฐ๋ 2์ (์์ ํธ๋ฆฌ์ ๋์ด + 1)์น์ด๋ฉด ์ ๋ ๋ถ์กฑํ์ง ์๋ค.
# 0: ํญ๋ฑ์, 1: lazy, ๊ธฐ๋ณธ 0
tree = [[0,0] for _ in range(1 << (math.ceil(math.log2(len(nums)))+1))]
def createWithRecur(start, end, index=1):
nonlocal tree
if start == end:
tree[index][0] = nums[start]
else:
mid = (start + end) // 2
createWithRecur(start, mid, index * 2)
createWithRecur(mid + 1, end, index * 2 + 1)
tree[index][0] = tree[index*2][0] + tree[index*2 + 1][0]
createWithRecur(0, len(nums)-1)
return tree
def propagation(tree, where, start, end):
'''
lazy๊ฐ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ ๊ฐ์ ์ถ๊ฐํ๊ณ ์์ ๋
ธ๋๋ก lazy ๊ฐ์ ์ ํํ๋ ํจ์
'''
if start != end:
tree[where * 2][1] += tree[where][1]
tree[where * 2 + 1][1] += tree[where][1]
tree[where][0] += tree[where][1] * (end - start + 1)
tree[where][1] = 0
return tree
def intervalUpdateLazy(tree, numCount, left, right, diff):
'''
lazy ๊ตฌ๊ฐ ์
๋ฐ์ดํธ ๊ตฌํ๊ธฐ
left, right : ์์ ํ๊ณ ์ ํ๋ ๋ฒ์
start, end : ํ์ฌ ๊ณ์ฐ ์ค์ธ ๋ฒ์(ํ์ฌ index๋ฒ์ ๋
ธ๋๊ฐ ์ปค๋ฒํ๋ ๊ณต๊ฐ)
index : ํ์ฌ updateํ๋ ๋
ธ๋
diff : ๋ณํ๋๋ ๊ฐ
'''
def updateWithRecur(start, end, index=1):
nonlocal tree, left, right, diff
if tree[index][1]: # ์ด์ ์ ์์ lazy๊ฐ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ ์์ ๋ค lazy ์ ํ
tree = propagation(tree, index, start, end)
if end < left or right < start: # ๊ตฌํ๋ ๊ตฌ๊ฐ์ด ๊ด๊ณ ์๋ ๊ฒฝ์ฐ
return
if left <= start and end <= right: # ํด๋น ๋
ธ๋๊ฐ ์ปค๋ฒํ๋ ๊ตฌ๊ฐ์ด ์์ ํ ํฌํจ๋ ๊ฒฝ์ฐ
tree[index][0] += (end - start + 1) * diff
if start != end: # ๋ง๋จ ๋
ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ,
tree[index * 2][1] += diff
tree[index * 2 + 1][1] += diff
return
else:
mid = (start + end) // 2
updateWithRecur(start, mid, index*2)
updateWithRecur(mid + 1, end, index*2 + 1)
tree[index][0] = tree[index*2][0] + tree[index*2+1][0]
updateWithRecur(0, numCount-1)
return tree
def intervalSumLazy(tree, numCount, left, right):
def getWithRecur(start, end, index=1):
'''
lazy ๊ตฌ๊ฐ ํฉ ๊ตฌํ๊ธฐ
index : ํ์ฌ ์ฒ๋ฆฌ ์ค์ธ ๋
ธ๋์ ์ธ๋ฑ์ค
start, end : ํ์ฌ ์ฒ๋ฆฌ ์ค์ธ ์ธ๋ฑ์ค ๋
ธ๋๊ฐ ๊ฐ์ ํฌํจํ๊ณ ์๋ ๋ฒ์
left, right : ๊ฐ์ ๊ตฌํ ๋ฒ์
'''
nonlocal tree, left, right
if tree[index][1]:
tree = propagation(tree, index, start, end)
if end < left or right < start:
return 0
if left <= start and end <= right:
return tree[index][0]
else:
mid = (start+end)//2
return getWithRecur(start, mid, index*2) + getWithRecur(mid + 1, end, index * 2 + 1)
return getWithRecur(0, numCount-1)
numCount, chngCount, sumCount = map(int, input().split())
number_list = [int(input()) for _ in range(numCount)]
tree = createSegTreeLazy(number_list)
for i in range(chngCount + sumCount):
cmds = list(map(int, input().split()))
if cmds[0] == 1:
_, fr, to, chng = cmds
intervalUpdateLazy(tree, numCount, fr-1, to-1, chng)
elif cmds[1] == 2:
_, fr, to = cmds
print(intervalSumLazy(tree, numCount, fr-1, to-1))
BIT (Binary Indexed Tree, ํ์ ํธ๋ฆฌ, fenwick tree)
ํธ๋ผ์ด(Trie)
์ฃผ๋ก ๋ฌธ์์ด๊ณผ ๊ด๋ จ๋์ด ์ฌ์ฉ๋๋, ํธ๋ฆฌ๋ฅผ ์ด์ฉํ๊ธฐ ๋๋ฌธ์ ์ด๊ณณ์ ํธ์
n์ง ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ด์ฉํด ์ฐพ๊ณ ์ ํ๋ ๊ฒ์ํ ๋ฌธ์์ด์ ๊ธธ์ด๋ฅผ $M$์ด๋ผ ํ ๋, $O(M)$์ด ๋๋ค.
class Trie:
def __init__(self, value):
self.value = value
self.childs = {}
def insert(self, word):
currNode = self
for letter in word:
if currNode.childs.get(letter):
currNode.childs[letter].value += 1
else:
currNode.childs[letter] = Trie(1)
currNode = currNode.childs[letter]
def search(self, query):
currNode = self
for i, letter in enumerate(query):
if currNode.childs.get(letter):
currNode = currNode.childs[letter]
else:
return 0
if i == len(query) - 1:
return currNode.value
def solution(
words, queries
):
trie = Trie(0)
for word in words:
trie.insert(word)
result = [trie.search(query) for query in queries]
return result
_articles/computer_science/algorithm/Python for Algorithms-Tree.md