STL-leverage audit: midpoint in seg trees, emplace+exchange in num_distinct_subsequences#230
Merged
Conversation
b4d9c10 to
ce89ffc
Compare
…istinct_subsequences
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Result of a file-by-file vet of all 144 library headers for missed STL leverage (C++11 through C++23). Stacked on #229 — merge after it.
Changes (4 files, 6 sites)
midpoint(tl, tr)in the recursive seg trees (5 sites)implicit.hpp(×2),persistent.hpp(×2),kth_smallest_query.hpp(×1):Shorter, states intent, and matches the existing use in
offline_incremental_scc.hpp. Identical value fortl < tr(std::midpointrounds toward the first argument). Thelazy_seg_treefamily is untouched — it deliberately usessplit()(power-of-two layout midpoint from the broken-profile blog), which is a different function.num_distinct_subsequences.hpp:emplace+exchange(1 line shorter, one fewer map lookup)Verified equivalent against the old version and a brute-force distinct-subsequence counter over 3000 randomized cases under ASan/UBSan.
Audit process
Four parallel scans over
data_structures_*,math+convolution+loops+contest,trees+graphs+dsu+flow, andstrings+monotonic_stack, followed by a pattern sweep for: midpoint/clamp/exchange/minmax candidates,find != end→ranges::contains, hand-rolled iota/binary-search/min-max loops, sort+unique+erase, map double lookups,__builtinleftovers, adjacent-element loops (views::adjacent/zipcandidates), and C++23 additions (fold_left,ranges::to,views::enumerate).Evaluated and rejected (so the next audit doesn't re-litigate)
clampinhagerup_kth_par.hpp:36—min(max(s, 2*K), d[l]+1)is NOTclamp(s, 2*K, d[l]+1): for shallow subtreesd[l]+1 < 2*Kandclampwithlo > hiis UB (asserts under_GLIBCXX_DEBUG). The min/max form is load-bearing.views::enumerate—rep(i, 0, sz(a))is 17 chars;for (auto [i, x] : views::enumerate(a))is 40. Never shorter at ColumnLimit 59; rejected as a class.views::zip_transform+ranges::maxformax_rect_histogram— saves one line but is UB on empty input where the loop returns 0, and reads worse.ranges::fold_left— zeroaccumulatecalls exist to convert.ranges::contains— zerofind(...) != end(...)patterns exist.exchangeforback()+pop_back()pairs (euler_path, complement_graph_ccs) — no STL pop-and-return; no improvement.<bit>passes:iota,partial_sum,minmax,mismatch,partition_point,ranges::sortwith projections, iterator form for subrange-returning algorithms.Validation
kth_smallest_pst,persistent_seg_tree,persistent_queue_tree,implicit_seg_tree,num_subsequences) compile clean withg++ -std=c++23 -O2 -Wall -Wextraand clangclang-format --dry-run --Werrorpasses on all changed files