Universe-bound ➔ holding only {106} still spans ~106 bits ➔ cost tracks max value, not count.
⚙️ Core Implementation
🔹 Bitwise set operations
member / add / remove / algebra
def contains(elems, i): return (elems >> (i-1)) & 1 # member: shift down, maskelems |= 1 << (i-1) # add: OR in a 1elems &= ~(1 << (i-1)) # remove: AND with negated maskunion, inter, diff = a | b, a & b, a & ~b # set algebra = bitwise logic
💡 Common Mistake:Counting is popcount, not maintained ➔ use int.bit_count() / Kernighan’s n &= n-1 (clears the lowest set bit), never a bit-by-bit Python loop; a lone huge value makes __len__ linear in that value.
⚖️ Core Decision Matrix
Operation
Complexity
Why
member / add / remove
O(1) (per word)
a few bitwise ops
union / intersection / difference
O(u/w)
word-parallel & / | / & ~
count (__len__)
O(u/w) POPCNT / O(popcount) Kernighan
no count maintained
space
u bits
1 bit/element — extremely compact for dense sets
When It Flips: right for dense small-integer sets with heavy membership/algebra (graph adjacency, dataflow analysis); wrong for sparse sets over a huge universe — use a hash set (O(1) expected, space ∝ count) or a Bloom filter (probabilistic, sub-linear).
📊 Exam Execution Trace
Manual Execution Trace
add 1, add 3, add 4, then ∪ {2,3}:
Step / State
Trigger Op
elems (binary)
Set
0 (Init)
init
0000
∅
1
add 1
0001
{1}
2
add 3
0101
{1,3}
3
add 4
1101
{1,3,4}
4
∪ 0110
1111
{1,2,3,4}
Applied Exercise
Problem: Quantify the word-parallel union speedup.
Derivation Proof / Hand-Calculation Walkthrough:
element-wise unionbit-vector union:O(u) comparisons:⌈u/w⌉ word ORs,w=64⇒≈64× faster (constant factor)
Final Extracted Output: ~64× constant-factor gain — same Θ order, dramatically smaller constant on dense universes.
🧠 Active Recall
What is "word-parallelism" and why does it make bit-vector set algebra so fast?
Hint: One instruction, 64 bits.
Answer
Short answer: One &/\| combines 64 memberships at once ⟹ union over u is ⌈u/64⌉ word ops.
Why:Constant factor ➔ ~64× fewer operations than element-wise — why bitsets dominate for dense small-universe sets.
Counting set bits naïvely is O(u) — describe Kernighan's trick and the hardware alternative.
Hint: Cost ∝ set bits, not universe.
Answer
Short answer:n &= n-1 clears the lowest set bit ⟹ loop runs popcount times (O(set bits)); POPCNT counts a word in one cycle.
Why:Skip the zeros ➔ both avoid scanning every bit, fast for sparse vectors.
When is a bit vector the wrong choice for a set, and what replaces it?
Hint: Sparse over a huge universe.
Answer
Short answer: Holding {1_000_000} wastes ~106 bits and counting is O(max value).
Why:Space ∝ count ➔ use a hash set (O(1) expected) or, if approximate membership is ok, a Bloom filter (sub-linear, one-sided error).