Translate (AKA immediate implementation problem)
- The problem is obvious that it should just be some data structures
- Segment tree CF474-D2-F
- Just DP, e.g. CF489-D2-F
Converting from brute force
- Sometimes it just works ??? this works especially well if you notice the input is extremely small
- Meet in the middle to be square root smaller CF525-D2-E CF1006-D3-F
- Backtracking to prune states
- Memoization (this is just dp lol)
Look at something in a new way
- Remove what seems to be impossible, NO it’s just not cause you don’t know some fancy technique, just try you best to convert the impossibility into something familiar!!
- ROOT THE TREE, probably a third of random tree problems on cf can be solved with this, it’s pretty powerful, either can be direction recursion, or use do
- CF486-D2-D (A bit different in that need to consider each node as a root)
- Sorting things
- CF732-D2-E
- CF474-D2-F
- JUST look at the array from left to right and consider elements one by one~ this works really well with permutation problems because permutations look hard but it becomes trivial when you actually just consider elements one by one Similarly, sometimes problems delete characters of a string/elements of array -> don’t think about how the string/array gets smaller, just think in terms of the original string/array
- Convert array to frequency array
- Splitting bigger things to smaller things/combining smaller things to bigger things
Splitting input into interesting groups
- Array problems -> fix one endpoint, interesting if we observe special properties as we extend right endpoint CF689-D2-D
- Group input into two buckets, where different methods apply for each bucket, AKA sqrt algorithms (27.1 in cases) CF1207-EDU-F CF797-EDU-E
- DP is a form of grouping?? many times it's hard cuz you can't find the important one CF489-D2-F
- Rectangle -> consider length/width as independent things CF1284-Hello-D
- Scanline -> intervals between event endpoints are interesting CF1284-Hello-D
- When you need to compare things one-to-one correspondence -> Canonical representations
- Order/smallest iteration that something repeats
- Complementary counting
- fix on something special to the problem and loop over/consider in terms of that
- Freely do things until the last step, but the last step automatically gets taken cared of anyways
- General independency
- e.g. Minimize Manhatten distance = minimize on Xs + minimize on Ys
- = n is equivalent to (<= n) — (<= n-1)
Find sparse/discrete/distinctive elements (AKA we like BIGGGGGG things)
- Binary exponentiation (when lots of identical things) CF702-EDU-E CF621-D2-E
- There aren’t that many powers, powers are op CF732-D2-E
- Using a number’s binary representation
- Find representatives
- A character is sometimes enough to represent a whole string
- Winner of elimination games
- Endpoints of intervals are usually interesting
- Not that many distinct prime factors for any reasonable number
Summarizing info
- Preprocessing is op (range sums, segment tree)
- Prefix sum (l, r) = (1, r)-(1,l-1) is just too op
- DP space saving
- CF489-D2-F (Don't actually need to keep track of which row we are currently on)
- Keep track of cumulative result as we scan for dp
- Where you store several cum arrays/fenwick trees, each for a certain remainder x modulo m
Observe interesting things
- "Intermediate value theorem"
- CF689-D2-D (As right endpoint exteneded, max only increases, min only decreases, so in between must be where max = min)
- One choice affects another, intertwined => dp? flow?
- Move by one consideration (THIS IS SUPER POWERFUL && NONOBVIOUS, SOMETIMES THIS KILLS PROBLEM IMMEDIATELY)
- Symmetry
- Things don't matter
- doesn't matter how many times you turn sth on/off, it only depends on parity
- The process must stop at some point, it might seem you like you need to simulate to infinity, but actually you only need to do a finite number of times)
- Increasing sequence??
- Trick with "optimized can always look a certain way", this is when you go, let's say you have something that looks a certain way, then if you change it in some ways then it's even better -> oh so the optimized thing must look a certain way
- Simulating something once is easy, but tle when trying all inputs => binary search (especially if the problem asks for min/max)
How can we save?
- Use set/map
- CF1284-Hello-D (So we can keep track of the maximum/minimum of endpoints of intervals we are looking at)
- CF525-D2-E (To quickly find number of subsets which add to a certain sum)
- Amortized analysis CF732-D2-E
- Sieve of Eratosthenes for analyzing complexity
DFS
- Standard counting
- Graph coloring
- For 2d grid
- Articulation points and bridges
- SCC
- Non obvious need to root the tree
Dijkstra
- Standard
- Fancier (keep track of something on top of distance)
other graphs
- Construct another graph based on original
- Can you go from source to destination with certain constraints
- Consider connected components separately
- Consider cycles
- Connected tree -> spanning tree
- Use dsu to union a component and treat is as one vertex
Sortings, relative order
- Reverse index/what you are thinking about
- Permutation inversions (ai > aj); useful to consider one element at a time
- Permutation/sortings with pairs containing original array index
- Somtimes sorting in an order helps solve the problem immediately (mentioned above)
- Indices/subindices/subsub indices -> practice to get familiar with this, it's just complicated to understand, but once you understand the problem is easy
- Using values as index
- idx/j subroutine, e.g. get counts of each block in 1, 1, 2, 2, 2, 3, 3, 3, 2, 2, 1, 1, 1, 1
- Use segment tree to store answer (forgot how exactly this works)
Local (greedy)
- Lexicographical order — ALWAYS consider digit by digit
- Powers of 2 consideration
- Again, move by one consideration
- Greedy where working out 1 or 2 things makes the rest work out
Global
- Can sometimes turn quadratics into linear by aggregating
- Double counting
Constructions
- Yes/No question? Sometimes one of yes or no direction is trivial
- Similarly, Even/odd consideration (sometimes the answer is always no for one of them)
- Think in simple global structure, aka don't think the problem is too hard, there needs to be something that is easy to think about
- Try to get rid of the condition in one go
Game theory
- Typical DP
- Some problems avoid the typical game theory dp thing Usually a big jump, where one player can just do something big and that's pretty much the end of game
- Elimination games => consider winner
Number theory
- Standard problem if you actually know all the basics
- Problems almost solved after considering gcd/consider when things are relatively prime (get extra assumption if divide by gcd)
Misc
- Algebra pattern finding, AKA simple induction; be careful with base case
- PIE
- WLOG one side is bigger
- TRIE for non obvious xor problem, tho this is a bit overused so hopefully you won't see it ever again