Segment trees, Fenwick trees, and offline tricks for range updates/queries
Build tree structures over arrays to aggregate ranges and support point/range updates efficiently.
Use when many queries/updates over ranges; consider offline methods (Mo's algorithm) when applicable.
Segment tree with lazy propagation for range updates/queries, Fenwick tree for prefix sums; offline Mo's algorithm for static queries.
Use this pattern when use when many queries/updates over ranges; consider offline methods (mo's algorithm) when applicable.
# Design Template (LRU Cache)
class LRUCache:
def __init__(self, capacity: int):
from collections import OrderedDict
self.cap=capacity; self.od=OrderedDict()
def get(self, key:int)->int:
if key not in self.od: return -1
self.od.move_to_end(key)
return self.od[key]
def put(self, key:int, value:int)->None:
self.od[key]=value; self.od.move_to_end(key)
if len(self.od)>self.cap: self.od.popitem(last=False)Tree over ranges with lazy propagation
class SegTree:
def __init__(self, arr):
n=len(arr); self.n=1
while self.n<n: self.n<<=1
self.t=[0]*(2*self.n)
for i,v in enumerate(arr): self.t[self.n+i]=v
for i in range(self.n-1,0,-1): self.t[i]=self.t[i<<1]+self.t[i<<1|1]
def update(self, idx, val):
i=self.n+idx; self.t[i]=val
i>>=1
while i: self.t[i]=self.t[i<<1]+self.t[i<<1|1]; i>>=1
def query(self, l, r):
l+=self.n; r+=self.n+1; res=0
while l<r:
if l&1: res+=self.t[l]; l+=1
if r&1: r-=1; res+=self.t[r]
l>>=1; r>>=1
return resBinary indexed tree for prefix sums
class Fenwick:
def __init__(self, n): self.n=n; self.bit=[0]*(n+1)
def add(self, i, delta):
i+=1
while i<=self.n: self.bit[i]+=delta; i+=i&-i
def sum(self, i):
i+=1; s=0
while i>0: s+=self.bit[i]; i-=i&-i
return s
def range_sum(self, l, r): return self.sum(r)-self.sum(l-1)Mo's algorithm / sorting queries
# Mo's algorithm skeleton
def mos_algorithm(arr, queries):
import math
n=len(arr); B=int(math.sqrt(n))
queries=sorted(queries, key=lambda q: (q[0]//B, q[1] if (q[0]//B)%2==0 else -q[1]))
curL=curR=0; curAns=0; ans=[0]*len(queries)
def add(i):
nonlocal curAns
curAns += arr[i]
def remove(i):
nonlocal curAns
curAns -= arr[i]
for idx,(L,R) in enumerate(queries):
while curL>L: curL-=1; add(curL)
while curR<=R: add(curR); curR+=1
while curL<L: remove(curL); curL+=1
while curR>R+1: curR-=1; remove(curR)
ans[idx]=curAns
return ansTree height log n.
Tree nodes ~4n.