A. BIT basics: updates, differences, k-th
- Dynamic Range Sum Queries~1300CSES 1648
- Range Update Queries~1400CSES 1651
- 1334
- Forest Queries II~1600CSES 1739
- List Removals~1700CSES 1749
- Multiset1900CF 1354D
- Messenger Simulator2000CF 1288E20-day #503
Ideas for this section
- 1648: set =
add(i, new − old). 1651: BIT on the difference array:add(l, v), add(r+1, −v), value =sum(i). - 1409 / 1288E: move-to-front: reserve m empty slots in front, each move clears the old slot and fills the next front slot; position = prefix count.
- 1739: 2D BIT (nested loops), rectangle = 4 prefix sums.
- 1749 / 1354D: BIT of 1s (or counts over values);
kth(k)finds the element, thenadd(pos, −1). 1354D's memory limit rules outmultiset.
B. Counting pairs / triplets (scan + BIT over values)
- Count Number of Teams1343LC 1395
- Maximum Crossings (Hard)1500CF 1676H2
- Greetings1500CF 1915F20-day #19
- 1800
- Nested Segments1800CF 652D
- Petya and Array1800CF 1042D
- Reverse Pairs~2000LC 493
- Number of Pairs Satisfying Inequality2030LC 242620-day #476
- Count of Range Sum~2100LC 327
- Enemy is weak1900CF 61E20-day #190
- 2207
- 2272
- Make Array Empty2281LC 2659
- Moving Points1900CF 1311Fsheet #48
Ideas for this section
- 1395 / 61E / 2179: fix the middle: (smaller on the left) × (larger on the right), each from a BIT. 2179: first rewrite nums2 as positions in nums1, then count increasing triplets.
- 1676H2: count pairs i < j with a[i] ≥ a[j] (≥, not >).
- 459D: pre[i] = count of a[i] in a[1..i], suf[j] = count in a[j..n]; count i < j with pre[i] > suf[j] by scanning right to left with a BIT over suf values.
- 652D: sort by right end; for each segment count earlier ones whose left is greater (compressed lefts).
- 1042D / 327: prefix sums:
P[r] − P[l] < t⇔P[l] > P[r] − t. Compress all P and all P − t, then count with a BIT while scanning r. - 493 / 2426: same scan, with the transformed value (
2·a[j],c[j] + diff) also compressed. - 1649: cost = min(# less, # greater) seen so far.
- 2659: visit in sorted value order; steps = count of remaining elements from the current position to the next (wrap around).
C. Offline: sort the queries
- Salary Queries~1800CSES 1144
- Distinct Values Queries~1900CSES 1734
- Little Elephant and Array1800CF 220Bsheet #64
- Mishka and Interesting sum2100CF 703D
- 2327
- Maximum Sum Queries2533LC 2736
Ideas for this section
- 1144: read all queries first, compress every salary that ever appears, BIT over values.
- 1734: sort queries by r; keep +1 only at the last occurrence of each value; answer =
sum(l..r). - 703D: XOR of even-count values = (XOR of range) ^ (XOR of distinct values); distinct XOR uses the 1734 trick with a XOR-BIT.
- 2940: answer = first index > max(a, b) with height > the taller one: max segment tree + descend (or offline with a monotonic stack).
- 2736: sort points and queries by x descending, insert y into a max structure over compressed y, query the suffix ≥ yᵢ.
D. Segment tree: point update, range query, descend
- Dynamic Range Minimum Queries~1300CSES 1649
- Iva & Pav1400CF 1878E
- Xenia and Bit Operations1700CF 339D
- Hotel Queries~1700CSES 1143
- Peaks in Array2154LC 3187
- Fruits Into Baskets III2178LC 3479
- Ant colony2100CF 474F
- Serge and Dining Room2200CF 1179C
- 2470
Ideas for this section
- 1878E: AND over [l, r] only falls as r grows → sparse table or segment tree + binary search on r.
- 339D: the merge alternates OR / XOR by level.
- 1143 / 3479: max tree; descend to the leftmost value ≥ x, then lower it.
- 3187: store 1 at each peak; an update changes only i−1, i, i+1; query (l+1 .. r−1).
- 474F: node = (gcd, min, count of min); the survivors are the elements equal to the gcd.
- 1179C: on the value axis, a dish adds +1 to the prefix [1..a] and a pupil adds −1 to [1..b]; the answer is the rightmost x with value > 0 (lazy add + descend).
- 2286: max tree for
gather(first row with ≥ k free seats, within maxRow), sum tree + a first-not-full pointer forscatter.
E. Custom merge node
- Subarray Sum Queries~1900CSES 1190
- SPOJ GSS1~1900SPOJ GSS1InMobi OA
- Prefix Sum Queries~1900CSES 2166
- Sereja and Brackets2000CF 380Csheet #49
- Palindrome Queries~2000CSES 2420
- Editor2100CF 1263E
- Non-Decreasing Dilemma2200CF 1567Esheet #63
- 2628
- 2697
Ideas for this section
- 1190 / GSS1: node (sum, best prefix, best suffix, best);
best = max(a.best, b.best, a.suf + b.pre). - 2166: node (sum, max prefix);
pre = max(a.pre, a.sum + b.pre). - 2420: forward and reverse polynomial hashes in two trees; a palindrome has equal hashes.
- 1263E: brackets as ±1, node (sum, min prefix, max prefix); valid ⇔ sum = 0 and min ≥ 0; depth = max prefix.
- 2213 / 1567E: node (prefix run, suffix run, best / count) + the end characters; join runs across the middle.
- 3165: node = 2×2 table best[first taken?][last taken?]; merge forbids taken|taken across the cut.
F. Lazy propagation
- My Calendar III~1900LC 732
- Falling Squares~1900LC 699
- XOR on Segment2000CF 242Esheet #62
- Range Module~2100LC 715
- Range Updates and Sums~2100CSES 1735
- Polynomial Queries~2100CSES 1736
- Circular RMQ2200CF 52C
- Rectangle Area II2235LC 850
- 2397
- 2816
Ideas for this section
- 732: range add + global max over compressed (or dynamic) coordinates.
- 699: range assign (new height) + range max on compressed x.
- 715: range assign 0/1 + "is the whole range 1" (min = 1), dynamic nodes.
- 2569 / 242E: lazy flip; ones = len − ones. 242E keeps 20 per-bit trees.
- 1735: two tags; assign wipes the pending add, add on top of assign just adds.
- 1736: add 1, 2, 3… = an arithmetic progression; tag (first, step), and two APs add up to one AP.
- 52C: a wrapped range = two normal ranges.
- 850: sweep x; the tree over compressed y keeps (cover count, covered length), no push needed.
- 2916: move the right end r; x adds +1 to the counts of left ends in (last[x], r]; Σ(c+1)² = Σc² + 2Σc + len, so keep the sum under range add.
G. DP sped up with a tree over values
- ~1800
- Subsequences1900CF 597C
- Best Team With No Conflicts2027LC 1626
- Optimal Partition2100CF 1667B
- 2280
Ideas for this section
- 673: BIT over values storing (best length, count); merge equal lengths by adding counts.
- 597C: k+1 BITs;
dp[j][v] = Σ dp[j−1][values < v]. - 1626: sort by (age, score);
dp = score + prefix max of dp over scores ≤: a max-BIT. - 2407:
dp[v] = 1 + max dp[v−k .. v−1]: a max segment tree indexed by value. - 1667B:
dp[i] = max dp[j] + sign(P[i] − P[j])·(i − j); three cases by sign → three max trees over compressed P storing dp[j] − j, dp[j], dp[j] + j.
H. Trees: Euler tour + BIT / segment tree
- Subtree Queries~1700CSES 1137
- Path Queries~1800CSES 1138
- Propagating tree2000CF 383C20-day #427
- Danil and a Part-time Job2000CF 877E20-day #401
- A Growing Tree2000CF 1891F20-day #472
- Water Tree2100CF 343D
- New Year Tree2100CF 620Esheet #108
- Path Queries II~2300CSES 2134sheet #110, HLD
Ideas for this section
- 1137: subtree =
[tin, tout]; point update, range sum. - 1138: root-to-v sum: changing v's value is a range add on v's subtree; the answer is a point query.
- 343D: fill v = assign the time on v's subtree range; empty v = set the time at tin[v] (a point). v is full ⇔ last fill of v > max empty time inside v's subtree.
I. Stretch (rare in OAs)
- Army Creation2200CF 813E
- The Child and Sequence2300CF 438D
- Multidimensional Queries2300CF 1093G
- Block Placement Queries2513LC 3161
Ideas for this section
- 813E: count i in [l, r] whose k-th previous equal value is < l: persistent tree or merge-sort tree (online).
- 438D: range mod: recurse only where max ≥ x; each mod at least halves the value, so the total work is small.
- 1093G: for each of the 2^(k−1) sign masks keep a max and min tree of the ± sum; answer = max over masks of (max − min).
- 3161: ordered set of obstacles + a max tree of "gap ending at x"; a query = max on [0, prev obstacle] and the last gap.