All Problems
Every problem in the library
Finding a Centroid
Problem Summary:
Given a tree of N <= 2e5 nodes, find a centroid, meaning if it were the root, every subtree has at most floor(n/2) nodes.
Notes:
A naive thought is enumerate the tree, check the sum up above this node (so everything outside the subtree), and the sum of our subtree minus 1, and if those are both <= floor(n/2) we have a subtree. This doesn't guarantee a find though. Imagine a spoke tree and the spoke is the root. Actually we want to compare the max of any child subtree size to floor(n/2) and the up outside region too. Every tree has a centroid, logic is kind of like this: call f(node) the max size of any piece when we cull node from the graph. If f(node) <= floor(n/2) we finish. Otherwise there is 1 piece > floor(n/2), which is equivalent to 1 piece > n/2. We move our node towards that subtree piece. After moving, everything outside that subtree could not exceed n/2, because we just said that subtree was >n/2. But the size of our subtree has now shrunk as we moved towards it. Something like that.
Drill Type:
Mindsolvere-read, mostly for centroid
Solutions:
Sliding Window Mex
Problem Summary:
Given N <= 2e5 numbers <= 1e9, and K <= N, find the MEX of all windows of size K
Notes:
1/ O(n log n), we fixed sliding window where we store MISSING values. We only need up to N values, not max(arr), because the MEX cannot be >= N. So we add and remove and just query sortedList[0]. 2/ O(n log^2 n) probably TLEs. We store PRESENT values in a sorted container and use binary search to find mex. Since find k-th is logN then each binary search iteration takes logN time. 3/ We use fast set on MISSING values for O(n * log_64(1e5)). We store all MISSING values in the fast set, do updates, and query next(0) which takes log_64(U) time. I think other data structures like persistent seg tree, wavelet tree, etc, maybe be able to do online variants or even with updates
Drill Type:
Mindsolvejust re-read
Solutions:
Fixed-Length Paths I
Problem Summary:
We have N <= 2e5 nodes and K <= N. Find how many paths in a tree have exactly K edges.
Notes:
1/ O(n log n) Each node returns a map of # edges -> count of how many paths with those edges We small to large merge To update the entire map at once when we return up, we increment an offset by 1 good practice with the offset trick, C++ syntaxes, etc One note: we also have to score any paths that go from a child directly to our node, which can be easy to forget, one way is to consider, when we select the heavy child, we also add a path of size 0 (representing our root node, it has nowhere to go yet), now any other light children will be able to merge with that 0, but this also feels weird to me 2/ O(n log n) centroid decomp probably intended
Drill Type:
Implementre-implement #1, probably learn #2 lol
Solutions:
Path Queries
Problem Summary:
We have a tree of N <= 2e5 nodes with values <= 1e9. And Q <= 2e5 queries which are either node point updates, or root->node path sum queries.
Notes:
Obviously HLD could work here but its O(n log^2 n). Instead we will use an euler tour which works on sums because they are invertible. We create a global timer=0 and DFS in some arbitrary order. When we enter a node we set tin[node] = timer++ (set to timer, then increment). When we exit a node we do tout[node] = timer, we do NOT increment. So the total array is still size N. What does this mean? Well tout[node]-tin[node] happens to be the size of the subtree. [tin[node], tout[node]) is also the half-open interval of that subtree which we could use for subtree queries but I prefer to do it by size. But what about paths? Think of it more like an event based sweep line, when we enter a node we are in its subtree, the event "starts". We add vals[node] to tin[node] because any root->node2 path, where that node2 is in the subtree of node, needs to include the sum of node. But this stops happening at tout[node]. So for every node's initial value we add it to tin[node] and subtract it from tout[node]. Now to get an arbitrary root->node path sum we think, well some nodes are going to be in the subtree of that node, we don't want those. So we stop at tin[node] because that happens before any children are visited. But what about other nodes we visited first, but they ended before we reach our current node? Like we went in and out of their subtrees. Well their sums won't contribute because they got removed via tout. So any nodes still "active" are basically our ancestors and their sums contribute. Now we can get path sums because the sum query from root->node is invertible. Every time we do a point update, we find the old value, the new value, get the new difference, apply that difference to tin[node] and -1*diff to tout[node] A root->node sum query is a st.querySum(0, tin[node]) then, it's like prefix sums of the active events basically. Also worth noting unrelated but if we want to do range adds on subtrees but only point queries, we can use a normal seg tree. To range add we do st.add(tin[node], diff) and st.add(tout[node], -diff) kind of similar. Now to point query we can do a prefix sum because it's all the "active events" kind of similar.
Drill Type:
Implementshould implement
Solutions:
Counting Paths
Problem Summary:
We have N <= 2e5 nodes and M <= 2e5 paths. For each node, count how many paths it is on.
Notes:
We could do a lazy hld seg tree where we range add by 1 and point query, mine TLEd on the last test though, prob can be optimized, it's O(n log^2 n) Or we do this euler tour trick, O(n log n) take two nodes A and B and their lca L (find via binary lifting) diffs[A]++ means the path flowing up from A to root gains by 1 diffs[B]++ diffs[L]-- we have to not double count the lca diffs[parent[L]]-- dedupe the path Now we do a postorder DFS to find the sum of diffs below us
Drill Type:
Mindsolvereview idea
Solutions:
Pishty and tree
Problem Summary:
We have N <= 1e5 nodes in a tree and edges that are weighted <= 1e9. We have Q <= 1e5 queries (node1, node2, K) and we need to know the XOR of all edges with weight <= K.
Notes:
First initialize a tree with all edges 0. Process queries in increasing K. Each K we add on new edges that have weight <= K, by setting them with a HLD. Now we do a range query for the XOR. I think we could also do some ETT thing
Drill Type:
MindsolveI guess just a reread
Solutions:
Black-and-White Tree
Problem Summary:
We have a tree of N <= 1e5 nodes which are either black or white chocolates (1s or 0s). We have Q <= 1e5 queries (node1, node2). For each query, find the simple path between those two nodes. We want to find the number of triplets of nodes (A, B, C) where all 3 nodes are on the simple path node1<>node2, and any pair from the triplet has at least one black chocolate among that path A<>B, B<>C, and A<>C. Find the # of triplets for each query.
Notes:
It's hard to find the # of triplets where every triplet pair has a black chocolate between them, so we do complement counting. We basically want to find bad triplets. A bad triplet is one where A<>B is fully white-only, or B<>C. A<>C would be implicitly bad then. We use HLD with seg trees. We want this information: -length of the seg node segment -count of black chocolate cities -length of the white-only prefix on that seg node -length of the white-only suffix -number of white-white chains, meaning # of pairs where all nodes on that path are white -number of bad triplet in that seg node To aggregate: The hard ones are new bad triplets and new white-white pairs New white white pairs are the white-white pairs in the left and the right, and also the aSuffix * bPrefix length since we pick 1 white from each New bad triplets is: -bad triplets fully in the left or the right -number of white-white pairs on one side * length of other segment, as we can pick any node -we can ALSO form a white-white pair via the aSuffix and bPrefix, and pick a third node But that third node CANNOT be in the aSuffix or bPrefix because we would have counted this before Also note we need to reverse the data for one side because this operation is not commutative
Solutions:
Subtrees And Paths
Problem Summary:
Given a tree of N <= 1e5 nodes and Q <= 1e5 queries. Support "add X to every node in this subtree" and "what is the max on this a...b path?"
Notes:
Lazy seg tree with HLD for log^2 n queries!
Drill Type:
Mindsolvequickly review that HLD can support subtree and path updates if we DFS order in the "visit heavy child first" method
Solutions:
Path Queries II
Problem Summary:
Given a tree of N <= 2e5 nodes, each node has a value. Support point node updates and path range max queries.
Notes:
It's heavy light decomp for O(n log^2 n). Let's go over the structure of a heavy light decomposition and its proofs: Also reference: https://www.youtube.com/watch?v=_G_LMuLWMaI First the idea, we can decompose a tree into heavy and light chains. If we want to query a path decompose it into logN chains, and each chain query takes logN time, then we get log^2 N query time. At a node, we find its largest sized child subtree (arbitrary if tie). If we travel down from our node to that child, that is a heavy edge. When we do a path query imagine the max # of chains we must cross as we go up from a node A to its LCA. If we pass at most logN light edges we also pass at most logN heavy chains (since heavy chains are only divided by light edges). Every time we cross a light edge, our current subtree size at least doubles in size, so there are logN at most. We want to store data structures for each heavy chain, or each single-node light "chain". We could store a different one for each or try to use a single array, like one big segment tree, that is basically a bunch of tiny segment trees for each chain. To do this, we need each heavy chain to be contiguous in our big array segment tree. Then to query that chain we can just query the indices of the end points of that chain inside the array. We need a few things to get started: -par[node] generally useful for parent -depth[node] can be generally useful -size[node] the subtree size, used to determine heavy children -heavy[node] the heavy child of a node, or -1 if no children -seg[segNode], a standard segment tree simultaneously handling every node at once -pos[node], a tree nodes position in our "linear" virtual array that we squish the tree into, we also feed this linear array into the segment tree to build on it so pos[top of heavy chain] <-> pos[bottom of heavy chain] is like a contiguous segment in our seg tree, or more like a contiguous range of our linear array which we feed into the seg tree and build on top of, and now if we need some index range say 3...7 in our linear array we don't even need the linear array, we just feed the seg tree those endpoints and it can find it with the tl tr recursive querying -head[node] the top of the chain for a node, either itself if light, or the top of the heavy chain if heavy Most of these are easy to set up. To get pos so that every heavy chain is contiguous, we basically keep a global timer, do a dfs order, and visit heavy children first always. To get the head we just do dfs(node, chainHead) and if recursing to a light child reset the head to that child. Now we have positions of every node so we can create a linear array. Build a seg tree using these positions. Set up a point update where it gets a node in the public interface, we convert to its position using our pos array, and we update that point. For path range maxes there are a few options: 1/ We build lift tables to find kth ancestor and lca. In a path we compute their lca. Now we do upQuery(startNode, excludedAncestor) on two separate paths up, then separately include the LCA. To do that query, we do a query from our node to the head[node], again using pos array. Even for a light node it's just a range query on a single node using the seg tree that's fine. We then move up by 1 with a parent array to get to the next chain. The moment head[currNode] is the same as head[excludedAncestor] we are on the same heavy chain (or the same node, a "light node") and we slow down. If our current node equals the excluded ancestor we are on the light node so we just return our current result. Otherwise both our current node and the excluded ancestor lie on the same heavy chain. We want the node right below the excluded ancestor. We could use kthAncestor + depths array. Or we could use a trick, pos[excludedAncestor] + 1 would be the node right below it because of how our dfs order timer works. 2/ We avoid kth ancestor, lca, and binary lifting entirely. We do a dual walk from a->lca and b->lca at the same time. WLOG we assume a's head is deeper than b's head. It is always safe to range query a<>a's head then jump to parent of a's head. Once the heads of a and b match, either they are the same node or they are on the same heavy chain and one of the two is an lca. We range query from a to b either way. How is the dual walk safe? Honestly a bit confusing, if you visualize some cases (A is on a heavy chain, B on a light node, etc etc) it kind of makes sense. Both implementations are in the CSES result and the github code, the dual walk is commented out. Note I think a link-cut tree might be logN per query
Drill Type:
Implementshould implement a working version, at LEAST in top down python or something and pass a few tests, ideally C++ though
Solutions:
192. Word Frequency
Problem Summary:
Given a words.txt of space separated words, output a word -> frequency mapping
Notes:
We use awk which is a terminal based scripting command, honestly best to read the code I have comments explaining how it works and its kind of cool
Solutions:
193. Valid Phone Numbers
Problem Summary:
Given a file.txt output all valid lines that are phone numbers given 2 allowed formats
Notes:
# grep searches for lines matching a pattern, automatically reads in every line and outputs every line # -E gives extended matching # the middle part is just a regex i stole from online lol
Solutions:
195. Tenth Line
Problem Summary:
Given a file.txt output the 10th line
Notes:
# normally tail reads last 10 # -n sets the number of lines, + prefix flips to mean start from # pipe symbol takes the output and redirects it to an input in the next command # head prints first lines of something, -n 1 makes it just the first line
Solutions:
3225. Maximum Score From Grid Operations
Problem Summary:
We have a 2d matrix of size NxN (N <= 100) with cells <= 1e9 in it. We will paint vertical black strips (see picture) starting from the top in some columns, we can pick how far down to go for each column. Then the overall score is the sum of white cells horizontal to a black cell. Find the max score.
Notes:
A naive dp is: dp(colI, prevPaint, prevPrevPaint) and we loop on new options to paint. We need both prev and prevPrev because when we paint some amount of cells, we might paint a lot in this column and thus score cells in the column behind us, but we need to dedupe if 2 columns ago accounted for those. We normally score the column we paint, forwards (we gain score for the future column on the right). But we also need to score backwards. Like think if our current column we only paint 2 cells, and two columns from now we paint 100, that needs to score backwards. But we need to dedupe. To speed this up we track a best dp where we have scored the previous column, and a best where we havent. These are initialized to all 0s and we can even start on column 1 in our loop because we can't get any score with just the 0th column. We loop over the new painted amounts and the previous painted amount and use this state machine like updating pattern kind of. n^2 loop inside the outer n loop makes O(n^3). I think we can do top down like dp(colI, prevPainted, prevScoredBoolean) and loop on the new painted amounts, prev scored is either true or false if we scored it or not There is some O(n^2) optimization and I think even a log based one in the solutions tabs.
Drill Type:
Mindsolvejust review the idea of having these two different dps
Solutions:
C. Maximum Set
Problem Summary:
A set of integers S is beautiful if for every two numbers X and Y in the set, either X divides Y or Y divides X. We are given L <= R <= 1e6. Find all beautiful sets with integers in that range. We need to output 2 numbers: -max possible size of a set with these constraints -# of sets with the same length as the max
Notes:
For the condition to hold, every number needs to build up bigger and bigger. Like if a 2 is in the set and we want to add another number to the set, we must add a multiple. Say 10. Now {2, 10} is the set. We want to add another, it must be a multiple of 10 (we don't worry about it being a multiple of 2 as it implicitly is, since 10 was). Say 40. Obviously the max length set is just doubled every time, so {L, 2L, 4L, 8L, ...}. We compute this. We could use any multiplier at any point, so {X, 5*X, 2*(5*X), ..} If we ever use a multiplier of 4 or bigger that is bad as we could replace with two 2 multipliers and increase the length. So a 3 multiplier is the most allowed. We cannot use two of those though because that would multiply by 9, which is more than using three 2x multipliers. So we optionally allow a 3x multiplier. We can binary search for the largest starting number where we allow one 3x multiplier. Same with no 3x multipliers allowed. O(n log n). I think the editorial just uses math instead of binary search, like integer division. To compute "the largest number X, when multiplied by some multiplier, is <= R". I think they just floor divide R by the multiplier or something.
Solutions:
C. Two Arrays
Problem Summary:
We have to make two arrays A and B of length M <= 10 with numbers N <= 1000. Each A_i should be <= B_i, and A is mono-increasing and B is mono-decreasing. How many ways?
Notes:
0/ A naive dp is dp(m_i, prevA, prevB) and we loop over the next A and B to pick. This is O(m * n^4). 1/ We speed this up with prefix sum DP. The bottom up version is very trippy. We basically have pf[prevA][prevB] is the answer for those cases. We loop over the M elements. We build this prefix. Building this prefix is odd because it's like a prefix from 1...prevA and prevB...m, like the top and bottom portions of the ranges. The way to build this is inclusion exclusion. pf[a][b] = cache[a][b] + pf[a-1][b] + pf[a][b+1] - pf[a-1][b+1]. So we build this in n^2 time. Now in our dp cache we just set all of dp[prevA][prevB] to equal the pf value. Since the # of ways to make a sequence have a new A and new B value is the sum of the prefix options. Overall O(m * n^2). Also to seed the dp I did it by considering the first pair of elements already placed, felt easier as a base case than trying to come up with values when no elements have been placed 3/ We can imagine the increasing array A and the decreasing array B, where they never cross, as one long increasing array if we flip B in reverse. Now to compute the # of ways to form this increasing sequence of length 2*m is just a naive dp(m_i, prevNum) and loop over new nums. O(2 * m * n^2) 4/ The above but we prefix sum optimize. O(2 * m * n) 5/ Some combinatorics solution (editorial) with stars and bars or something but I didn't learn it
Drill Type:
Mindsolvejust re-read all
Solutions:
D. Maximum Sum of Products
Problem Summary:
We have two arrays A and B with numbers <= 1e7, sizes <= 5000. We can reverse one subarray in A. We want to maximize the sum of all A_i * B_i.
Notes:
dp(l, r) is the sum of the portion of we reverse a[l...r]. We enumerate all n^2 options and get the reversed sum. We use prefix and postfix for the outside ranges.
Drill Type:
Mindsolvequick re-read since reversing a subarray normally is trippy but the n^2 allowance makes it easy
Solutions:
D. Maximum Subarray
Problem Summary:
We have N <- 2e5 numbers where abs(num) <= 1e9. We have to add X <= 1e9 to exactly K <= 20 positions, and subtract it from the others. What is the maximum sum subarray we can make?
Notes:
Remember we can do interval DP on stuff like this! Kind of like kadane's top down. We just do dp(i, opsLeft, state). Where state is before or inside the current subarray. There's a lot of edge cases and tricks with the state machine like implementation. there are also greedy ideas apparently
Drill Type:
Implementgood practice to implement this tricky state machine / interval thing top down
Solutions:
2777. Date Range Generator
Problem Summary:
Write a JS function that yields date values from start to end, incremented by step
Notes:
get the current and ending dates, while current <= end we yield and increment
Solutions:
2722. Join Two Arrays by ID
Problem Summary:
Given two arrays of objects we need to merge the objects with a spread
Notes:
Basically store a map of id -> object, for the second array spread if it already existed
Solutions:
2690. Infinite Method Object
Problem Summary:
Write a function that returns an infinite method object, like this: Input: method = "abc123" Output: "abc123" Explanation: const obj = createInfiniteObject(); obj['abc123'](); // "abc123" The returned string should always match the method name.
Notes:
We use a proxy. It basically intercepts any get access and returns a function that returns the name of the property that was invoked.
Solutions:
2649. Nested Array Generator
Problem Summary:
Make a javascript generator of nested lists
Notes:
yield* basically recurses on the inner list, otherwise yield
Solutions:
A. Disturbing Distribution
Problem Summary:
We have N <= 100 numbers <= 100. We want to delete the array. We can pick a subsequence {a, b, c, ...} that is ascending and score a * b * c * .... What is the min score to delete?
Notes:
We want to delete elements separately. Except for 1 we want to delete it with others if we can. We can delete all 1s with another element if any element is on the right of the furthest 1.
Solutions:
B. Everything Everywhere
Problem Summary:
An array is good of max-min = gcd of all elements. Given a permutation of length N <= 2e5, how many subarrays are good?
Notes:
Imagine an array with 3 elements: A, A+X, A+2X max-min = 2x But not every element can be divisible by 2x of course since they are off by X. Or any other value for that matter. So only arrays of size 2 need checking.
Solutions:
C. Mental Monumental (Easy Version)
Problem Summary:
We have N <= 2e5 numbers <= 1e6. We can replace every number (optionally) with that number % some other number. We can do this once. Then we want to find the MEX of the new array. Max MEX possible?
Notes:
First understand what the replacement operation does: On number 100 we could mod it by 1, 2, 3, ... 101 Note that 100%100 is 0. 100%99 is 1. And so on down to 100%51 is 49. So we can cover all of 0...49. Anything 50 or below like 100%50 or 100%33 is guaranteed to be <= 49 so those doesn't help. So for even numbers we can reach a range 0...v//2 - 1. For odds we can reach 0...v//2. We can ALSO reach exactly V by modding 100 with anything >100. So a range might look like [0...49, 100] With these ranges we want to find the max MEX we can make. Some ideas: 1/ Sort the ranges perhaps by lowest reach range first. Greedily take the next required mex. If we can't take this, like if we are at mex=55 but the range is 0...49, we add 100 to a storage to use later and move on. We take from storage as we can. Sounds right but didn't end up working... We might not want to take from a range just because we can, maybe we want to save that higher single point. For instance if the single point is 10, like [0...5, 10] we could save that 10 for later, not use this range, build up to 9, take our 10, then maybe use a single 11 after, or more bigger ranges. It feels like there should be a way to make the greedy work but it's confusing to think about (and I think there is no way) The annoying problem is we don't know whether to save that later single bigger digit or not. 2/ Instead work backwards. See "can we make a MEX of 10"? First we need a 9. If the 9 is in a single position like [0...4, 9] we should take that 9 versus taking it from a range [0...20, 40] because it's never worse. So we binary search on the answer and do some bookkeepping I used a multiset for O(n log^2n)
Drill Type:
Mindsolvere-read, idea of what values we can get after mod, work backwards, covering a range with weird types of segments
Solutions:
D. Make Them Equal
Problem Summary:
We have N <= 1000 numbers all initially 0. We have a goal array B of N numbers <= 1000. We want to turn our initial array of 1s (call it A) into B in as many indices as possible. If we turn A_i into B_i we gain C_i <= 1e6 coins. We are allowed to use K <= 1e6 operations. In an operation we can take a number in A, some integer X>0, and make A_i = A_i + floor(A_i/X) So 100 we could floor divide by 6, get 16, and then get 100->116 in one operation. Find the max coins we can score.
Notes:
First we need to understand these floor operations. A naive approach is for each number from 1 to 1000, we could enumerate all denominator options from 1 to 1000, get their floor values, and find the new reachable number. We want to reach each target number in min moves. We could use BFS or DP. We could use quotient buckets to compute the transition faster. A number has rootN unique (number/x) floor options. To generate them, start by dividing by 1. Obviously we get num/1 = num, so that's one floor division option. What is the maximum denomiator we could have used to make num though? It's also 1. Better example: 100//21 is 4. What is the largest denominator that makes 4? Well do 100//4 and we get 25. If we got something like 25.2328... then the largest is 25 still. So we "jump" over all the values from 21-25 and know 26 produces a new number (3.84!). This allows a rootN transition. Okay now we have the min cost for each A_i to reach B_i. We have N <= 1000 possible bags each with a cost and a coin gain. Naive dp is dp(i, opsLeft) but that is 1e9 since K<=1e6. But we don't need this many operations ever... At most to get to any number in 1...1000 we need 12 or 13 operations (forgot), I tested with the BFS. So really our bound for operations is N*13 as we allow that many for each. Now the knapsack becomes tenable. Bundle splitting stuff or other techniques don't seem to apply here, it's really the cap on K that is the key component
Drill Type:
Mindsolvereview, cap on K was essential, quotient buckets is good too
Solutions:
1386. Cinema Seat Allocation
Problem Summary:
We have N <= 1e9 rows of cinema seats with 10 seats per row. 1-3, 4-7, and 8-10 form sections. We want to place 4 in a row, if they straddle a section it must be 2 and 2 on each side. We have M <= 1e4 blocked seats, how many groups can we place?
Notes:
basically groups are 2,3,4,5 4,5,6,7 6,7,8,9 and we can get at most 2. I just checked all 3 per row. Kind of a poorly worded question. Unoccupied rows just contribute 2 groups.
Solutions:
2624. Snail Traversal
Problem Summary:
We need to add a JS method to arrays to do a snail traversal of an array, see picture, but basically columns left to right in alternating direction
Notes:
First make sure dimensions line up, then just do it
Solutions:
2692. Make Object Immutable
Problem Summary:
Write a function that takes in an object and returns an immutable version with specific rules (see question)
Notes:
this is what a proxy is, it can intercept things. get and set can get the original object and other params, we have to do some recursive stuff to handle like obj.arr.push being denied, see the code it's pretty cool
Solutions:
2758. Next Day
Problem Summary:
Update the JS date class to have a nextDay function which gets the day after as a formatted string
Notes:
use `this` which is the instance of the class to grab the current date, find the next one, return that
Solutions:
2805. Custom Interval
Problem Summary:
We need a JS function like settimeout but it has a backoff time duration.
Notes:
We track a nextFreeId. When we start our procedure we do one call to set timeout with the initial required delay. We grab a fresh id from the nextFreeId and then increment nextFreeId for later use. We set our returned id from the initial set timeout in a map of id -> clear ids for the clear function to access. That single set timeout calls another function which reschedules itself with a new delay and updates the map with a new clear id
Solutions:
C. Infected Tree
Problem Summary:
We have a binary tree of N <= 3e5 nodes. Node 1 is infected. On a turn we can cut a node, trimming off that subtree. The node we cut dies but nodes in its subtree basically get saved. Then the infection spreads. Max # of nodes we can keep alive?
Notes:
We should either cut the left or right child, gaining that subtree sum (minus the node we cut) and recursing. No dp is needed.
Solutions:
C. How Does the Rook Move?
Problem Summary:
We have an NxN (N <= 3e5) chessboard. We place rooks one at a time on (r, c) and the opponent places an opposite color rook at (c, r) if they can (they cannot if r=c). Some moves we initially placed and the opponent responded. We place rooks such that no two attack each other (color does not matter). We place until we cannot place more. How many ways can we do this?
Notes:
To visualize the opponent moves just think of them reflecting moves over the major diagonal. Also note N rooks always get exactly placed. We can never place >N rooks (pigeonhole) and if we place fewer than N rooks it implies there is always some row with no rooks, and some column with no rooks, so their intersection can have another rook. We actually don't need to think about the positions so much. But rather the # of free rows left. We consider the topmost row with a rook. Say there are 2 rows that still need pieces. We could place on the r=c line now there is 1 row left. Or we could place the rook on any other available column in that row, which is basically the # of free rows left too (off by 1, since we don't count the r=c line). When we place it there the opponent mirrors in a necessarily free spot so we reduce the # of free rows by 2. And we could have placed on either side of the reflection line. So it just ends up being DP. There is also a combinatorics version where we enumerate on the # of type 1 moves (we place on the r=c line) we can do and use some other combinatorics I didn't look into it
Drill Type:
Mindsolveworth a re-read just about the fact we don't need to actually know the positions of the rooks, just the # of free rows left, and remembering that exactly N rooks can be placed on an NxN grid, and we can always add another rook if we haven't placed N yet
Solutions:
C. Star sky
Problem Summary:
We have N <= 1e5 stars with coordinates (x, y) <= 100. And Q <= 1e5 queries which correspond to a subrectangle of the sky. Stars have a max brightness of C <= 10 and each one has some starting brightness. Over time they go from brightness a, a+1, a+2, ..., C, 0, 1, ... For each query find the total sum of brightness of all stars in the sky at this point in time
Notes:
2d prefix sum [x][y][initStarBrightness] tells us the # of stars with that initial brightness in that range. Basically 11 2d prefix sums. For each query we do 11 loops also, tabulating over initial brightnesses, computing the current brightness, and adding.
Solutions:
C. Interesting Sequence
Problem Summary:
We are given N <= X <= 1e18. We want to form some sequence N & N+1 & N+2 & ... & M = X Find the smallest M that does this, or -1 if not possible
Notes:
Notice how the AND value can only ever go down, and at most log(N) times too. So we could binary search for the smallest M that does it. Call the AND of elements L...R rangeAnd. If the rangeAnd(n, some binary search value) is exactly X, we update answer and try a smaller range If the rangeAnd is too big, we need to AND more values, search higher If the rangeAnd is too small, we ANDed too many values, search fewer To rangeAnd L...R it's actually just the shared prefix of the two. The code is nice. The intuition is basically start at the largest bit of L and R, if they match then they always will for all numbers from L...R. Move on to second bit. If they don't match, then it's a fail. We could also do rangeAnd with digit DP. We could do this without binary search too, some observations: since N&N+1&... can only drop, and never gain bits, if X has a bit N doesn't we fail. So X must be a submask of N. Claude explanation I didn't read: For each bit b set in N, the smallest m ≥ N where bit b of m becomes 0 is flip(b) = ((N >> (b+1)) + 1) << (b+1). Once m hits flip(b), bit b is gone from the AND forever. Bits set in both N and X must survive → m < flip(b). Bits set in N but not X must die → m ≥ flip(b).
Drill Type:
Mindsolvereview, mostly for range AND
Solutions:
C. Zero-Sum Prefixes
Problem Summary:
We have N <= 2e5 numbers abs(num) <= 1e9. Some numbers are 0s. We can replace a 0 with any integer. Find the max # of prefix sums that total 0 after these replacements.
Notes:
An initial thought might be to turn a 0 into the inverse of the sum before it, like [2, 0, 2, 4, -4, 4, -4] we might turn the 0 into a -2 to score it: [2, -2, 2, 4, -4, 4, -4] But actually that just guarantees our ...0 prefix gets a point. We should instead look RIGHT because we can affect all the prefixes bigger than us. We see the (4,-4) and (4,-4) pairs are basically 0s, but there is a 2 right before it in index 2 that is offsetting us. If we set our 0 to a -4: [2, -4, 2, 4, -4, 4, -4] then we would score 2 points instead. So for each 0, walk right and maintain a map of the maximum prefix sums from that 0 onwards, the highest frequency determines how much we can score. Include the initial 0 in that frequency map too. Also, we have to score the prefix before the first 0, separately.
Drill Type:
Mindsolvejust reread
Solutions:
C. Even Path
Problem Summary:
We have an NxN (N <= 1e5) grid. To represent this grid we have an array R and C of size N, and grid[i][j] is R_i + C_j We have Q <= 1e5 queries (point1, point2). Those two points are always even numbers. Can we connect the two points with a path that stays on even numbers?
Notes:
At first it seems complex, maybe we have to go really far right from one point, up, then loop back up. But this cannot happen, if we could go really far right, then up, we could also go up immediately. Because it means going right our parity never changed, and so going up from that point on the right our parity didn't change, we could just go up immediately. So precompute how far right and up we can go from cells to maintain the same parity, I used dp, but we could union find on adjacent parity that match. Then check if they can reach. We can always do it in a single right then up (or right then down) path.
Solutions:
B. Factorial Divisibility
Problem Summary:
We are given N <= 5e5 numbers <= X <= 5e5. Determine if A_0! + A_1! + ... is divisible by X! (NOT x)
Notes:
One observation, say all the terms are >= 5!, like 5! + 5! + 8! + 6! Then obviously we are divisible by all 1...5 because we are just adding terms divisible by those. Note this does NOT necessarily mean we are divisible by 5! (but maybe it's true?) For instance if we are divisible by 2 and 4, say 4, we are not necessarily divisible by 2*4. So just being divisible by 1,2,3,4,5 doesn't mean we are by 1*2*3*4*5 (but again maybe it is, not sure if there is a proof...). The claim we make is different. If every term is >= 5! that means every term is also divisible by 5!, since 6! = 6 * 5! for example. So obviously we are divisible by 5!. But the moment we hit 6? Are we divisible by it? We can take everything >=6, so (6! + 8!) and call it (stuff divisible by 6!) and then take all the 5 factorials (5! + 5!) and see it is not divisible by 6!. Because we require 6 of them. So basically we get a counter of every factorial. We loop up starting at 1. Look at how many 1! we have. Maybe it's 5. Two 1!s add to a 2! so that combines into 2! + 2! + 1!. Well we know this is like (stuff divisible by 2!) + (something not divisible by 2!, since we don't have enough to combine, I mean 1 * 1! is literally smaller than 2! so it could never be divisible). So we know 1! is the biggest stopping point. But if we had 6 of them, it forms three 2!s, we bubble up a count, and keep going.
Drill Type:
Mindsolvere-read
Solutions:
D. Lucky Chains
Problem Summary:
We are given N <= 1e6 pairs (x, y) <= 1e7. For each pair we keep incrementing by 1, so (x+1,y+1), (x+2,y+2), and so on, forming a chain. A pair is lucky if gcd(x, y) = 1, find the length of the longest lucky chain for each pair
Notes:
First note if X and Y share a factor it isn't lucky and the chain is size 0. If they are coprime, any individual factor from X or Y would never be an answer because X&f != Y%f Any factor of X+? and Y+? must also be a factor of Y-X because of the offsets. So we want to analyze each factor of Y-X and check the smallest one >= X. But constraints are tight. Note we can just check prime factors, not all factors. So we need an SPF sieve in N log log N up to 1e7 and then to prime factorize we use the spf which is worst case logN time since all primes reduce by at least 2x division.
Drill Type:
Mindsolvereview ideas of using a sieve and spf instead of trying to spam pollard rho everywhere, mod remainders is cool too
Solutions:
3464. Maximize the Distance Between Points on a Square
Problem Summary:
We have a square of side length S <= 1e9. We have 4 <= P <= 1.5e4 points along the borders. We also have 4 <= K <= 25 which is how many points we have to select. What is the maximum minimum manhattan distance we can have between the K selected points? Basically we want to space out things as far as possible.
Notes:
First thing to note, manhattan distance feels annoying because we are working on perimeters. But actually because 4 <= P we know we could never space out all the points by > S anyway. This means that an annoying situation like 2 points on opposite sides of the square, having a smaller manhattan distance than perimeter distance, actually does not bother us since we don't need to consider manhattan distances > S anyway. Next we map the border points to a flat array see code. Let's binary search on the answer so we introduce a log(S) factor since it's at most S. For each answer we can consider every point as a starting point. It feels like we maybe have to do some annoying circular array technique for our binary search but we actually do not need to. Since SOME point is going to be the starting point, say starting from (0,0) moving clockwise around the square, whatever point that is, when we pick that as a starting point, we can just travel the array right only, ending back at the bottom edge of the square (moving towards 0,0). So no circular binary searching needed. We consider P possible starting points. For each point, we binary search for the next point spaced out by our guess in logP time. After doing this K times, we check if our ending point wrapped around too close to our starting point. This gives log(S) * P * logP * K. 2/ We could drop the K by building jump tables... For each possible distance in the binary search we spend P log P time finding the next position for every point, and then P log K time building out the jump tables. Now when we enumerate starting distances, we immediately jump ahead K spots in log time with the jump tables and check if it wrapped too far. 3/ I think there is an even better one than jump tables using two pointers: https://leetcode.com/problems/maximize-the-distance-between-points-on-a-square/solutions/8098454/java-binary-search-with-feasibility-chec-x48a/?envType=daily-question&envId=2026-04-25 4/
Drill Type:
Mindsolvere-read full notes, liked ideas about starting points only having to go right and not loop back to the start in the binary search, liked jump tables idea, see code for the flattening of border points -> array
Solutions:
D. Unfair Game
Problem Summary:
Bob picks some power of 2 <= 1e9. Alice will take her turns (she plays only) trying to bring it down to 0. She can divide / 2 if even, or she can subtract by 1. We give her K <= 1e9 turns. How many numbers <= N can she not reach 0?
Notes:
Think in binary, a subtract operation turns the LSB from 1->0, a divide removes that last 0. Obviously we need to divide out until we clear the MSB. But among those there might be other 1s in the middle we subtract out. It's combinatorics, for each possible MSB, like 10000 or 100 we check how many other 1s can be placed in the tail 0s, such that alice still has enough operations to clear it, basic nCk. Handle the edge case of the number equaling N exactly, separately, because we can't add 1s under it or it would exceed N. Digit DP can probably be used too
Solutions:
D. Jellyfish and Mex
Problem Summary:
We have N <= 5000 numbers <= 1e9. We will delete the array one at a time. We pick a number, delete it, and add MEX(arr) to our score. We want the minimum score, what is it?
Notes:
Naive way of thinking works O(n^2), our current mex is some value. We can clear out a lower value and get a new mex. It's not guaranteed which one to clear out though. Like maybe there's a LOT of 0s so we shouldn't clear those out, there's a single 5 let's clear it out quickly to stem the bleeding, etc. Note it's not just clear one type then clear 0, we can actually chain them, so we need dp(mex). Base case is mex=0 we pay 0 to clear the remaining array. We test all unique values. A bit of a trick, if the current mex is 10 and there are three 5s, and we clear those three 5s, we only pay 10 twice, because we pay the mex after we clear the number. This makes the score updating a bit annoying but the cleanest way was to add on a 5 in the recurrence (see long long score = paid + nxt + x), the +x basically makes it so we pay that 5 in the future, because otherwise the 5 we pay now doesn't get counted, but this makes it so basically any mex that wasn't the first captures that extra time. If it doesn't make sense don't worry it was just a clean way to handle something.
Drill Type:
Mindsolvejust re-read honestly such a great question
Solutions:
B. One Night At Freddy's
Problem Summary:
Super weird problem, basically we have L <= 2e5 seconds in the night, and N <= L animatronics, every second one of the animatronics danger levels rises by 1 (initially all are 0). We don't know which rises basically it can be picked adversarially. We have N <= L flashlights at given second times, we can flash an animatronic to reset its danger. The overall danger is the maximum final danger at the end of the night. What is the smallest value of this? Also # animatronics * L <= 2e5
Notes:
The idea is kind of like this, say the enemy only incremented 1 animatronic over and over, we would just flash it repeatedly, and end up scoring L - last flashlight time (it increments at the very end un-interuppted). So obviously the enemy would want to increment more animatronics, it could increment 2, then you execute your final flash, and they spend all their increments on the non-flashed one at the end which is at least as good as the only ever increment 1 case. If we have X flashlights remaining there isn't a point for them to increment >= X+2 animatronics. We can only flash X of them, so dispersing flashes among the other 2 is bad. I kind of lost the intuition now but basically they want to increment exactly X+1 where X is the current amount of flashlights we have. They do this "evenly" to sort of build up this weak frontier. If we they went more min-maxed in their incrementing we would nuke the big ones quickly first so they need to do it evenly. I simulated but probably could be simulated faster.
Drill Type:
Mindsolvejust refresh the idea of an even defensive increment before reset
Solutions:
C. Where's My Water?
Problem Summary:
We have an N <= 2000 grid that is H <= 1e9 tall, bottom blocks are land top are water (just see pictures). We can place two drains which drain water from any cell that can travel laterally and down. Max water we can drain?
Notes:
My idea was for each drain position, assess all prefixes and suffixes containing that drain. We can form a prefix of the prefix for the best results (sounds confusing, really its not though) and then test splits points. I'm sure there's many more ideas I won't really look into them though.
Solutions:
1516. Move Sub-Tree of N-Ary Tree
Problem Summary:
Given a tree and two nodes P and Q, move P into the subtree of Q, some weird rules if Q is inside P
Notes:
basically just follow instructions, different cases for the positions of P and Q, track parents
Solutions:
2791. Count Paths That Can Form a Palindrome in a Tree
Problem Summary:
Given a tree of N <= 1e5 nodes with <= 26 letters on edges, find how many paths we can have where we re-arrange the letters to form a palindrome.
Notes:
SOLUTION: small to large It would be nice if at a node we could enumerate all down-chains in all its descendants, well that is what small to large does We track a map of parity bitmask -> count since things like 0010000 can form a palindrome. When we merge in light nodes there's a few things that happen: 0/ the base case for us is a map of bitmask 0 -> frequency of 1, and we call shift(mask) before we bubble up to account for that edge (or we could just insert the actual mask and not shift it) 1/ light node mask can XOR with itself to form a mask of 0, which allows a palindrome (no odd frq letters) 2/ light node mask can XOR with any mask that is exactly 1 bit wrong against that, to form a palindrome mask with a single bit set 3/ we should enumerate all these options first, then fold in the lightnode, or it pollutes 4/ we also want to score all paths that end at the node exactly, I added handling at the end for both the no single bit set, and the single bit set cases, maybe we could just initialize the heavy node we pick with the root nodes data? that felt confusing though because things were on edges not nodes. 5/ When we do add the root node data later, it's annoying because we want to modify the bitmask of every node in our final heavy output, since they all get affected by this edge, to handle this we can store an offset in our Info class 6/ When merging default dicts I ran into some issue where reading a 0 in a map created an empty 0:0 key:value pair or something like that, it TLEd for me, I don't know if it actually affects complexity, claude seemed kind of unsure, to fix this I just made the .get() and .add() abstractions to the info struct to deal with it -I did a manual implementation in the submission at the bottom but it was hard -Easiest is to build the abstractions in the info class of my top submission SOLUTION: prefix XORs First get the XOR of every root to leaf path. Now any two nodes that have a palindromic bitmask XOR form a path. We can do this with a single loop + hashing.
Drill Type:
Implementre-implement, tricky handling of Info class, offset shifting, dealing with small to large on edges
Solutions:
2568. Minimum Impossible OR
Problem Summary:
We have an array of N <= 1e5 numbers <= 1e9. We can pick a subset and bitwise OR them together. What is the smallest number we cannot make?
Notes:
We basically need all bits in a range b...32 to make at 32 bit number. So we check 1, 2, 4, 8, 16, etc if they exist
Drill Type:
Mindsolvequick reread
Solutions:
1576. Replace All ?'s to Avoid Consecutive Repeating Characters
Problem Summary:
We have a string of letters and ?, replace every ? so no two letters are adjacent
Notes:
Only need up to 3 letters per option, when we write we need to read res[i-1] not s[i-1] in case the previous letter was a ?
Solutions:
626. Exchange Seats
Problem Summary:
We are given a SQL table of seats and people, we need to swap every 2 seats, except the last if odd
Notes:
literally can just do CASE WHENs on the parities
Solutions:
Basic Die Game V
Problem Summary:
We roll a 6 sided die. We can choose to reroll for $1. If we stop we get a payout of the upwards face. Basically we get at most 1 reroll. Expected payout?
Notes:
An average roll is 3.5, so a 4 5 and 6 won't reroll a 3 wouldn't reroll either since we pay $1 So a 1 or 2 (1/3rd of the time) we lose $1 and then get $3.5 on average, so $2.5 payout 50% 1/3rd of the time. 2/3rd of the time we get an average of a 4.5 (from 3 4 5 6). ends up being 23/6
Reflip
Problem Summary:
We are given 8 coins and flip all at once. After we can reflip any amount one time. We get $1 per head. Payout?
Notes:
A single coin basically gives $0.75 payout, since 3/4 times it pays $1, so $6 total
Black Or Yellow
Problem Summary:
We have 4 balls, two black two yellow. We pick out random ones one at a time without replacement. Before each one we guess the color, if we are right we get in dollars the # of balls in the container before we chose it. Expected payout?
Notes:
First guess we get $2 EV since it is 2|2 Now it splits into 2|1 0.33 chance we get nothing, 0.66 chance we get $3, so this layer has ev $2 Keep writing it out like this there might be a linearity of expectation idea too
Drill Type:
Mindsolvereview, we can literally just write it out
Bear And Bull Market
Problem Summary:
Price of a stock starts at $100, then drops 1%, then goes up 1%, forever, what does it converge to?
Notes:
After one cycle price is $99.99 so we lost 0.01% P_n + 100 * (0.9999)^n which approaches 0 Is there a formal proof? I wrote this before idk: for any positive integer r r = e ^ (ln r) r^n = e^ (n ln r) same with the fraction .9999^n = e ^ (n ln .9999) since ln(.9999) < 0 we have e^-inf which is 0
Side Add
Problem Summary:
We roll a standard 6-sided die. After, given we rolled K, we roll a (6+K) sided die, find the expected value that appears on the second roll.
Notes:
We condition on the first roll all with equal chances, so if first roll is a 1, we have a 7 sided die which gives us 4 on average, and so on, average all those up
Drill Type:
Mindsolvequick review condition on first idea
Ship Stops
Problem Summary:
We are sailing from 1 island to another. Travel time takes 12 minutes but there are 5 wave checks. Four of the waves stop us with 25% chance and add a minute. Last stops us with 75% chance and adds 4 minutes. Find expected duration.
Notes:
The stops are entirely independent so I don't think we even need linearity of expectation idea really, but yeah just add them up
Rough Day
Problem Summary:
A bagel factory delivers good (G) and bad (B) bagels. If a bagel is G the next one is G with 2/5 chance. If B the next one is B with 3/5 chance. The first bagel is bad. Find the # of expected bagels that pass until another bad one.
Notes:
Note each bagel has a 2/5 chance to be G and 3/5 to be B regardless. So what is the expected # of trials to get a B where the independent chance is 3/5? It's just the inverse 5/3 but we can do a formula. E = 3/5 * 1 + 2/5 * (1 + E), kind of recursive E = 0.6 + 0.4 + 0.4 E E = 5/3
Drill Type:
Mindsolvereview the formula representation
Generational Wealth I
Problem Summary:
We generate a random number from (0, 1). We can keep it or generate a new one. Payout is the last number generated. Find expected payout.
Notes:
If the first one is above 0.5 we keep it and get 0.75 in expectation, otherwise we get 0.5, so 0.625
Drill Type:
Mindsolvereview
Lock And Key Pair
Problem Summary:
You have 5 unique locks with 5 unique keys for them, each unlocking one lock. What is the max # of times we need to test locks to identify all that open them?
Notes:
4 fails for first key, 3 for second, 2 for third, 1 fail for fourth, then no fails for last
Integer Polygon
Problem Summary:
How many values of N are there such that a regular n-gon has interior angles that are integer values?
Notes:
Exterior angles sum to 360, but cannot be 180 or 360, so take all other factors of 360, since exterior angle must be an integer which makes interior one an integer
Drill Type:
Mindsolvequick review
River Length
Problem Summary:
You are in a river with an unknown length and current speed. If you remain stationary (not swimming) in the river, it takes you 6 seconds to reach the opposite bank. If you swim downstream at a speed of 3 feet per second, it takes you 4 seconds to reach the opposite bank. What is the length of the river (in feet)?
Notes:
W = width Passive movement goes W/6 feet per second If we go down at 3fps our speed is (3 + W/6) fps d = r * t W = 4 * (3 + W/6) W = 36
Drill Type:
Mindsolvereview how to set up equations
Kiddie Pool
Problem Summary:
You are trying to fill up an inflatable kiddie pool. One hose can fill it up in 20 minutes. Another hose can fill it up in 10 minutes. If the pool is full, it takes 15 minutes to drain out the water after the drain is opened. How long does it take in minutes to fill the pool with both hoses and the drain being open?
Notes:
h1 fills C/20 per minute h2 fills C/10 per minute d drains at C/15 per minute total rate gain C/12 per minute so 12 minutes
Revolver Time
Problem Summary:
Jenny is firing her revolver, which has 6 chambers. The time from the first shot to the last is 1 minute. Assuming a uniform firing rate, how many seconds will it take Jenny to fire 3 shots?
Notes:
1 gap = 12s so we use that to get 24s
Doubling Bacterium
Problem Summary:
A bacteria population doubles every 10 minutes. At t₁ = 55 minutes, the population consists of 200 bacteria. How many bacteria does the population consist of at t₂ = 95 minutes?
Notes:
It doubles 4 times so 3200
Seating Drama
Problem Summary:
On a circular table of 5 seats, five people denoted 1, 2, 3, 4, 5 are seated. 4 wishes to sit immediately to the right of 2 while 2 sits immediately to the right of 5. Additionally 1 does not want to sit next to either one of 2 or 5. Who is to the left of 5?
Notes:
just basic logic
Solutions:
2D Paths I
Problem Summary:
We have a 6x6 grid, we are in the bottom left and want to move up and right, how many ways to reach 6,6?
Notes:
We need to interleave U and R which is the normal 12!/(6! * 6!) idea
A. Olympiad Date
Problem Summary:
We have N <= 20 digits <= 9. We are trying to form "01 03 2025" from the digits, when could we have earliest assembled that date?
Notes:
just loop and counter, have need could work too I guess
Solutions:
B. Team Training
Problem Summary:
We have N <= 2e5 students with skills <= 1e9. A team is strong if its strength is >= X (<= 1e9). Strength is # of members * min skill. We want to partition the students (subsets, not subarrays) and find the max # of strong teams we can get.
Notes:
Start at the biggest, if that alone isn't strong we have to take someone smaller, the biggest can't be the min. Take the next smallest, keep going until we are strong, then that is a team. No reason to add more.
Drill Type:
Mindsolvejust re-read, kind of a weird greedy, basically we have to start from the strongest, not the weakest
Solutions:
2897. Apply Operations on Array to Maximize Sum of Squares
Problem Summary:
We have N <= 1e5 numbers <= 1e9. In an operations we can take i and j, and perform these two updates at the same time: nums[i] = (nums[i] AND nums[j]) nums[j] = (nums[i] OR nums[j]) We can do this operation any # of times. After this, we will pick K <= N elements and sum their squares. What is the max sum we can get?
Notes:
Imagine two numbers like this: 111 111 000 000111 111 Basically the operations "pass" non shared bits from one number to another, like this: 000 111 000 111 111 111 We can do this in both directions This intuits that maybe we can greedily form as big numbers as possible. So we count up all the bits in all numbers and assemble the largest K possible. We can see this is doable because we can take any number that has some 0 bits, and any number which has 1 bits for those spots, and pass it over. So we can basically just keep filling up any number with as many 1s as possible.
Drill Type:
Mindsolvejust re-read notes, the bit operations sometimes sound tricky but are easy to understand
Solutions:
3338. Second Highest Salary II
Problem Summary:
Given a SQL table of employees find all employees who make the second highest distinct salary in their department
Notes:
I avoided some partition thing, instead I select all employees WHERE then do a subquery where the count of distinct salaries greater than our salary is 1
Solutions:
608. Tree Node
Problem Summary:
We have a SQL table of tree nodes with a node id and a parent id, return a table showing whether a node is a root, inner node, or leaf
Notes:
root is when parent id is null, inner node is when some other node has us as a parent (subquery check), else leaf
Solutions:
3054. Binary Tree Nodes
Problem Summary:
We have a SQL table of tree nodes with a node id and a parent id, return a table showing whether a node is a root, inner node, or leaf
Notes:
root is when parent id is null, inner node is when some other node has us as a parent (subquery check), else leaf
Solutions:
2615. Sum of Distances
Problem Summary:
Given N <= 1e5 numbers <= 1e9 we want to find some array of the same length. Arr[i] is the sum of |i-j| for all nums[j] == nums[i]. Find this array
Notes:
Map val -> indices For each unique value we have a list of indices, for each of those indices we want to find the sum of distances to all other indices 1/ Compute the answer for bucket[0] initially by looping over all i in 1...end of bucket When we move from bucket[i] to bucket[i+1] the answer changes in a predictable way, the # of elements less than us we know, and we know they grow each in distance by the bucket[i] to bucket[i+1] gap, and ones on the right move closer 2/ Or we could probably do some prefix / suffix thing
Drill Type:
MindsolveQuickly reread first idea
Solutions:
2003. Smallest Missing Genetic Value in Each Subtree
Problem Summary:
We have N <= 1e5 nodes each with different values, for each subtree, find the smallest missing value in it
Notes:
0/ Some weird union find variant? didn't look into it https://leetcode.com/problems/smallest-missing-genetic-value-in-each-subtree/solutions/1458284/union-find-with-thinking-process-a-bonus-l4n2/ 1/ Small to large with sorted lists, we merge it, to find smallest missing we binary search + find kth which is log^2 n (I think because there is no O(1) find kth?), overall thing is n log^2 n because of merging sorted lists too 2/ Dylan had an O(n log n) version https://leetcode.com/problems/smallest-missing-genetic-value-in-each-subtree/solutions/1458702/java-small-to-large-merging/ He did small to large using hash sets but each node also stored its smallest missing value, so when we bubble up all the children, I guess we can do something with that 3/ O(n) Well note since values are distinct anything missing the single 1 is going to have answer 1. Only ancestors of 1 need to be recomputed. We could walk up from the 1 node adding all elements in and seeing the smallest missing, I guess with a SortedList in N log N but there is some O(n) boolean array idea I didn't look into... 4/ tree flattening Flatten into euler tree, now we need to find smallest missing in a range for a bunch of l...r ranges Normal mo's is like with a SortedList so n root n log n, too slow I think tin has some weird trick remember, like MEX with mo's, using sqrt decomp with O(1) update rootN query or something, so N root N time? REVIEW THIS We can use fastset too, on the absent values not in the tree, basically we can insert and remove from the set in log_64(U) and to find the smallest missing it's just next(1) which is log_64(U), so we get N root N * log_64(U) got an AC here in C++ https://leetcode.com/problems/smallest-missing-genetic-value-in-each-subtree/submissions/1985777388/ Note our fastset is on abset values, we could also do it on present values, but then to find the MEX we could binary search and call prev(i) which is logU * log_64(U) WE COULD ALSO USE SEG TREE: Remember we want to find smallest missing value in a range L...R (for each tree range) We could use a seg tree on values, each leaf stores lastPos[v], internal nodes store the minimum lastPos over its range of values Sort queries by increasing R lastPos[v] = -1 for everything since nothing is seen yet Sweep r = 0, 1, 2, ..., n - 1 update lastPos[val[r]] = r with a point update For every query (L, R) with R==r answer it now: smallest value with a lastPos < L? How to answer a query (L, R). We want the smallest value v with lastPos[v] < L. Do a segment tree descent from the root: At each node, look at the left child's minimum. If left.min < L, then some value in the left half has lastPos < L, so the answer lives in the left half — recurse left. Otherwise, every value in the left half has lastPos ≥ L (meaning they all appear in [L, R]), so the answer must be in the right half — recurse right. At a leaf, return the value index. OR PERSISTENT SEGMENT TREE: Didn't look into it yet: Version 2: Persistent segment tree (makes it online) The core idea. Instead of mutating one segment tree as we sweep, we keep a snapshot after every update. roots[r] = the root of the segment tree as it was after processing position r. To answer query (L, R), use roots[R] and do the same descent as before — querying at R without having to be physically there in a sweep. How to store N snapshots without blowing up memory. Naively, N copies of a tree with O(V) nodes = O(NV) memory, catastrophic. The persistence trick: when you do a point update, only O(log V) nodes on the path from root to leaf actually change. So create new versions of only those nodes, and have them point to the old (unchanged) children. Each new "version" of the tree shares almost all its nodes with the previous version. Result: each update creates O(log V) new nodes. Total memory: O(N log V). For N = V = 10⁵, that's ~2·10⁶ nodes — fine. Pipeline. Build initial tree with all -1s. roots[-1] = this tree. For r = 0 to N-1: roots[r] = update(roots[r-1], val[r], r). For each query (L, R): answer = query(roots[R], L). Total complexity. O((N + Q) log V) time, O(N log V) memory. Same time as Version 1 but online. When you'd use this. If the queries come one at a time and you must answer each before seeing the next. Or if the queries depend on previous answers. Or if you're inside a competitive programming problem that explicitly forces online. For this LeetCode problem, all queries are known upfront, so Version 1 is simpler. I think we can do wavelet tree for range mex? and even with updates??? https://codeforces.com/blog/entry/137068 And 3d mo's??? for n^(5/3)
Drill Type:
Mindsolvejust re-read
Solutions:
The Grass Type
Problem Summary:
We have N <= 1e5 nodes with labels <= 1e9. We want to find the total # of pairs (u, v) where A_lca(u,v) = A_u * A_v Basically the total # of pairs where their node labels multiply to form their LCA. How many pairs are there?
Notes:
Small to large merging, we store counters of number -> frq, as we merge we can look up the complement value to update result
Drill Type:
Mindsolvejust another re-read of notes
Solutions:
3590. Kth Smallest Path XOR Sum
Problem Summary:
We have a tree of N <= 5e4 nodes with values. We have Q <= 5e4 queries (node, k). Call the path XOR sum of a node the XOR from the root of the tree down to a node. Each query gives us a node and wants us to find the Kth smallest distinct path XOR sum in that subtree, or -1 if it doesn't exist
Notes:
Small to large merging, base case is we return a SortedSet with just the single XOR from the root to that leaf, we do this via dfs(node, aboveXor) To merge two SortedSets (or SortedLists) just get the heavy child and merge in light childs ensuring no duplicates if using a SortedList We answer queries at the time we get the SortedList fully set up for a subtree The problem is a bit weird because normally we think of small to large as merging things coming from below, but in this case we are still doing that, it's just we track the aboveXor during the thing 2/ https://leetcode.com/problems/kth-smallest-path-xor-sum/solutions/6870202/trie-merging-in-nlogn/ There is some crazy trie merging idea The idea is you have a binary trie, top node is MSB, and each node stores a counter for the # of elements in that subtree So to find kth smallest is easy, we just do a trie-walk based on the counts, cause anything on the 0-bit child subtree is smaller than anything in the 1-bit child So we can find kth in log(MAX) Then using some weird way to merge tries I didn't learn we can get n log MAX I guess 3/ I think tin found some online way using a sqrt persistent seg tree
Drill Type:
Mindsolvethe small to large feels weird here because it's using a SortedList and because the path XOR comes from above, but that's actually fine, just peak at code
Solutions:
E. Lomsat gelral
Problem Summary:
Given a tree of N <= 1e5 nodes of colors <= N, a color C is dominating in a subtree if there are no other colors appearing more times than C (so multiple can be dominating). For each vertex find the sum of its dominating colors.
Notes:
1/ We can use mo's and a flattened tree to get n root n 2/ We can use small to large For each node we track a frequency of color -> count, we track our max frequency, and the sum of all dominating colors Store this in an Info struct Sort the children by map size, pick the first as the heavy child, grabbing it with move() (I think this is needed?) Loop over other ones, merge them in, updating the sums/frqs as needed, also merge in the root node Update result of our node before we bubble up the map, I think required to do it like this because the maps get bubbled and re-used and we want to capture the data now while it is fresh 3/ Someone said we can use centroid decomp and they were a GM 4/ They also said n*DSU is doable in the editorial comments idk how There is another idea which is like small to large but avoids merging unordered maps which is slow. We use a global array and global dominatingSum and maxFreq representing the values for SOME subtree. First we loop over all light children processing them, walk down the child, fill out the data, get the answer for that light child. When we bubble back up we reset the global data. Then we loop into the heavy child, get the data, answer for that subtree, go back up, but don't drain. Now loop over all small ones again, adding them back up, now we have a full tree. Proof of complexity is something like nodes are part of light children only logN times since they at least double in size when they walk up. Didn't practice this.
Drill Type:
Implementgood to practice Info struct, merging, grabbing nodes with C++ syntax, etc
Solutions:
A. Die Roll
Problem Summary:
Some basic math question honestly not re-reading
Notes:
just very basic math and gcd
Solutions:
Maximum Xor Subarray
Problem Summary:
Given N <= 2e5 numbers <= 1e9, find the maximum XOR of any subarray
Notes:
Remember XOR of subarray is just prefix XORs of r and l-1 So add all prefix XORs to a bit trie, each time we add then find the best XOR against any of those not adding to drills because I have more complex bit trie problems in drills
Solutions:
E. Sausage Maximization
Problem Summary:
We have an array of numbers, we want some prefix (can be nothing) and some suffix (can be nothing) that don't overlap and have a max XOR, find that XOR
Notes:
bit trie can find max XOR against numbers in a set, so prefix/suffix that
Drill Type:
Implementshould probabily implement the bit trie and read its functionalities...
Solutions:
3772. Maximum Subgraph Score in a Tree
Problem Summary:
We have a tree, nodes are good or bad. A good node gives +1 and bad node gives -1. A subgraph of the tree is the sum of scores of its nodes. For each node, find the max score subgraph containing that node.
Notes:
Reroot DP First compute down[node] Then I used full[node] since the answer is just that minus down[child] to get the up portion, or we can gain 0 from that up portion if we don't want it, basically a pretty simple case
Drill Type:
Implementsure why not, pretty easy just another solve
Solutions:
2538. Difference Between Maximum and Minimum Price Sum
Problem Summary:
We are given a tree of nodes with values. The price sum of a path is the sum of node values on that path. The tree can be rooted at any node root of your choice. The incurred cost after choosing root is the difference between the maximum and minimum price sum amongst all paths starting at root. Return the maximum possible cost amongst all possible root choices.
Notes:
First observe the min is just the node itself so we really just care about the max price sum path for each root First compute down[node] which is max price sum where we go down Then I did up[node] (we have to seed it before dfs2! since its just price[node]) and res[node]. Update res[node] in the root call. I build a prefix and suffix and used the exclude trick but it was annoying. https://leetcode.com/problems/difference-between-maximum-and-minimum-price-sum/submissions/1985534087/ Or we can do a trick where we store top 2 price sums going down, and which child we went through for the best one. Now at a child, if the parents best didn't go through that child, our up[child] can just use that, otherwise we use second best. That's for the go up from child -> parent -> back down to a sibling case. I actually found this way easier to write, separating upThenDown, upUp, and down. https://leetcode.com/problems/difference-between-maximum-and-minimum-price-sum/submissions/1985561955/ We could also not store the best child node to pass through from the parent, but I think we could just recompute the scores if we went from node through child node, and compare if the biggest down from node was through the child, but I found storing the best node we passed through easier
Drill Type:
ImplementI have some similar implementation practice in CSES tree distances 1, but for this one I want to specifically try the concept "store the best child we passed through" cause I found it really easy to implement
Solutions:
834. Sum of Distances in Tree
Problem Summary:
Given a tree, find the sum of distances from a node to all other nodes, for every node
Notes:
Reroot DP First I did down[node] and we compute it using the size of subtrees as well Then I did full[node], seeded full[0] The distance for a child is just the parent node distances, but all child nodes move 1 closer, all other nodes move 1 away
Drill Type:
Mindsolvere-read notes / quick glance at code, have other reroot dp in implements drills
Solutions:
2581. Count Number of Possible Root Nodes
Problem Summary:
We have a tree. We want to find the root so we make guesses, in a guess we pick two nodes U and V and ask "is U the parent of V"? Bob doesn't tell us which guesses are right but tells us how many are right. How many possible roots can there be?
Notes:
Reroot dp first solve down, so in a subtree find how many valid guesses there are now we solve full, we seed full[0] and update res[child] style, maybe can do a different way Only transition is the single reroot edge
Drill Type:
Mindsolvejust re-read code, have enough reroot dp drills I think
Solutions:
836. Rectangle Overlap
Problem Summary:
Given two rectangles find if they have a positive area overlap
Notes:
We can find intersected AREA of each dimension and multiply those 1/ casework- -A contains B -B contains A -A fully left of B -B fully left of A -A partially left of B (I think we can check either the left or right edges? a few ways? if we process this last) -B partially left of A 2/ clamp- Everything reduces to taking the max of the left edges and the min of the right edges, and the difference is their width We have to max with 0 because non-intersecting regions have negative area max(0, min(x2, x4) - max(x1, x3))
Drill Type:
Mindsolvere-read notes
Solutions:
2682. Find the Losers of the Circular Game
Problem Summary:
We have K <= N <= 50. N people from 1 to N. We start at person 1, they pass to the right by K, then person 2 passes to the right by 2*K, and so on (circular array). Game ends when someone gets the ball for a second time. The losers are those who never got the ball, return these.
Notes:
Simulation using a counter
Solutions:
1933. Check if String Is Decomposable Into Value-Equal Substrings
Problem Summary:
We are given a string, decompose it into blocks like [aa, b, yyy, aaa] Given a digit string s, decompose the string into some number of consecutive value-equal substrings where exactly one substring has a length of 2 and the remaining substrings have a length of 3. See if we can do this^
Notes:
I basically looped over letters, tracked streaks, tracked how many were divisible by 3, and how many required that extra 2 (we need exactly one of these), but it's annoying because the way I code this it requires another check outside the for loop for the last streak some improvements: 1/ append a '#' to the end which flushes out the last character 2/ we can use itertools.groupby req2 = 0 for _, g in groupby(s): n = sum(1 for _ in g) r = n % 3 if r == 1: return False if r == 2: req2 += 1 if req2 > 1: return False return req2 == 1
Drill Type:
Mindsolvereview tricks
Solutions:
3907. Count Smaller Elements With Opposite Parity
Problem Summary:
We have N <= 1e5 numbers <= 1e9. For each index i, find the # of indices j where i<j and nums[j]<nums[i] and nums[j] has an opposite parity to nums[i]
Notes:
I used two SortedLists for odds and evens and looped backwards
Solutions:
E. Covering Points with Circles
Problem Summary:
We are given N <= 1e4 points X,Y <= |1e5|. The points are uniformly and randomly distributed in some unknown sized rectangle. We are given a circle radius 100 <= R <= 1000. Guaranteed the circle doesn't exceed >10% of the area of the rectangle. We wish to place circles on the plane such that: -No two overlap -Each circle contains at least one point -We use at most N circles -89%+ of the points are contained by a circle Find such a construction where each circle has an integer center.
Notes:
First note the points are random, we need something that covers a lot of the plane. Hexagonal packing covers ~89%. Imagine row0 is aligned at y=0 so we have circles there. Rows in the next row above get nestled in-between, so offset by a shift of R. The vertical distance is r+root(3) (can derive from height of an equilateral triangle). See a hex packing diagram to get the idea. We actually space out the heights by ceil(r * root3) to ensure integer centers and the idea is this shouldn't produce a lot of loss of area. Now for each point try to find a circle containing it. First guess it's row based on the ceil(r * root3) distance. Similar math we use for the column (they're spaced by 2*R). Note we could center our circles anywhere since we are just tiling things, so centering at R,R might be easier. We get an approximate row and col but due to the way they nestle we aren't quite sure which circle it falls in, so I checked a 3x3 grid around that area. If any circle contains that point (euclid distance) we add that circle to the group. We can do this since we can spend up to N circles.
Drill Type:
Mindsolvereview
Solutions:
A. A Number Between Two Others
Problem Summary:
We are given X < Y <= 1e18. Y is a multiple of X. Find if there is a Z for: X < Z < Y Z is a multiple of X Y is not a multiple of Z
Notes:
First ensure there is at least one multiple between X and Y If there is I guess we could just pick the highest one, like Y-X, and if Y/X>=3 this always works In contest I did a more brute force approach
Solutions:
D. Exceptional Segments
Problem Summary:
Consider a sequence [1, 2, 3, ... N]. We are given X <= N <= 1e18. Find the # of subsegments L...R that contains N and has an XOR of 0
Notes:
Remember an XOR of L...R is pfXor[r] ^ pfXor[l-1]. But pfXors follow a pattern: Define f(k) = 1 ⊕ 2 ⊕ 3 ⊕ ... ⊕ k. f(k) follows a period-4 cycle based on k mod 4: | k mod 4 | f(k) | |---------|------| | 0 | k | | 1 | 1 | | 2 | k+1 | | 3 | 0 | Why? Well pairs of numbers that start with an even always XOR to 1. Like [4, 5] XORs to 1. We can write out the cases: ### Case k = 8 (k mod 4 = 0) f(8) = (0⊕1) ⊕ (2⊕3) ⊕ (4⊕5) ⊕ (6⊕7) ⊕ 8 = 1 ⊕ 1 ⊕ 1 ⊕ 1 ⊕ 8 = 0 ⊕ 8 = 8 Four complete pairs cancel, leaving k dangling. Result: f(k) = k. ### Case k = 9 (k mod 4 = 1) f(9) = (0⊕1) ⊕ (2⊕3) ⊕ (4⊕5) ⊕ (6⊕7) ⊕ (8⊕9) = 1 ⊕ 1 ⊕ 1 ⊕ 1 ⊕ 1 = 1 Five pairs → odd number of 1s. Result: f(k) = 1. ### Case k = 10 (k mod 4 = 2) f(10) = (0⊕1) ⊕ (2⊕3) ⊕ (4⊕5) ⊕ (6⊕7) ⊕ (8⊕9) ⊕ 10 = 1 ⊕ 1 ⊕ 1 ⊕ 1 ⊕ 1 ⊕ 10 = 1 ⊕ 10 = 11 For two things to XOR to 0 we want f(r) and f(l-1) to be equal. This happens when they are both 1, or are both 0. Specifically blocks of [0, 1, 2, 3] [4, 5, 6, 7] , ... And [2, 3, 4, 5] [6, 7, 8, 9], ... XOR to 0 And these are the only such cases, so a subarray XORs to 0 only with a composition of these blocks, in 1, 2, 3, ..., N To prove that we could basically write out the 4x4 matrix of cases and show only those hold So now we just count how many blocks of these forms exist and do some math
Drill Type:
Mindsolvere-read / refresh idea
Solutions:
C. Red-Black Pairs
Problem Summary:
We have a 2xN grid of red and black cells, N <= 2e5. We want to repaint some cells so we can do this: -group the cells into pairs -pairs of cells must be two adjacent cells -pairs must share a color Min # of repaints to make?
Notes:
I did bottom up DP, like prevMatch, prevBR, prevRB, kind of state machine logic, there may be some greedy as well
Solutions:
B. Alternating String
Problem Summary:
We have a string S of length <= 2e5 of A's and B's. We want to make it alternating (so ABAB... or BABA...). We can pick some subarray, invert all the letters, and optionally reverse it. Can we make it alternating?
Notes:
I think dp works but it gets fairly complex. I did casework: Count the consecutive blocks like [aaa, b, aa, bbb]. If any block of size >= 4 exists we fail. We can have at most a single block of size 3 (AAA -> ABA) and no other blocks of 2 or more). If we have blocks of size 2, we can split them up so like AA ... BB we place the ends here A|A ... B|B, so we can have at most 2
Solutions:
455. Assign Cookies
Problem Summary:
We want to give children cookies, each gets at most 1. Children have greed factors where they need a cookie at least g[i]. Each cookie has a size. What is the max # of children we can give a cookie to?
Notes:
Sort and then two pointers
Solutions:
409. Longest Palindrome
Problem Summary:
Given a string, find the length of the longest palindrome we could make if we rearrange
Notes:
Evens contribute, one odd
Solutions:
412. Fizz Buzz
Problem Summary:
Given N, return a fizz buzz array, if divisible by 3 and 5, FizzBuzz, just 3 is Fizz, 5 is Buzz, otherwise number
Notes:
Check 15, 3, 5, then number
Solutions:
268. Missing Number
Problem Summary:
Given all numbers from [0, n] except one find the missing one
Notes:
sum-subtract, xor everything against 1...n
Solutions:
87. Scramble String
Problem Summary:
We can scramble S to get T doing this: If length is 1, stop If length is >1, split it into two substrings at a random index, S = X + Y Randomly decide to swap the two, so S = Y + X Apply the algorithm on each X and Y Given S1 and S2, can S1 become S2?
Notes:
dp(l1, r1, l2, r2) and we test every scramble point. This looks n^5 but the # of states is n^3 because r2 is derived since the lengths are constant.
Solutions:
69. Sqrt(x)
Problem Summary:
Given X <= 2^31, find the square root rounded down without a built-in
Notes:
Binary search for the smallest number squared <= X there is some trick though where rootX is e^(1/2 log x) or something lol We could also use recursion. Base case is when x is 1. Note rootX = 2 * root(x/4). So we could use that recursive algorithm or something like that in logN too Newtons method does something too
Solutions:
66. Plus One
Problem Summary:
We have a list representing a longer number like [5, 3, 1, 0, 9] add 1 and return a new list
Notes:
Increment last one, carry while we have 10s
Solutions:
52. N-Queens II
Problem Summary:
Given an NxN (N<=9) board find the # of boards we can place N queens with no two attacking
Notes:
standard backtrack(row) where we have a rowSet, colSet, two diagSets We could also do backtrack(r, c) with the sets
Solutions:
51. N-Queens
Problem Summary:
We have an NxN (N<=9) board, output all boards with N non-attacking queens on it
Notes:
standard backtrack(row) where we have a rowSet, colSet, two diagSets We could also do backtrack(r, c) with the sets
Solutions:
C. Creative Snap
Problem Summary:
We have an avengers base. There are positions in the base each with some amount of avengers. The length of the base is a perfect power of 2. Thanos wants to destroy the base with minimum power. Starting with the whole base, he can: -If the length is at least 2, divide it into two equal halves and destroy them separately -Burn the base, if it has no avengers it takes A<= 1e4 power, if it has avengers it takes B * n_a * l power, where l is the length, B is <= 1e4, and l is the length of that base. What is the min power to destroy everything? 2^N is the length of the base, N <= 30, so the base is <= 1e9 length
Notes:
We can represent the problem as: recurse(l, r) The root level is (0, n-1) Second level is (0, n-1/2) (n-1/2 + 1, n-1) This forms 1 + 2 + 4 + 8 + ... + n at the bottom level. This is 2n-1 intervals. Think of it like adding binary: 0001 0010 0100 1000 (this is n) The sum is: 1111 Now this is too many because N <= 1e9. But the moment we have no avengers in a range we could early terminate. So how many ranges could contain an avenger? With M avengers each one could be in up to logN different sized subproblems so M log N which is tenable. We just need countAvengers(l, r). I did another binary search which gives us M log 2^N log M I don't know if we can drop that binary search (fractional cascading?), someone said something about master theorem: https://codeforces.com/blog/entry/64989?#comment-708754
Drill Type:
Mindsolveworth a read
Solutions:
B. Average Superhero Gang Power
Problem Summary:
We have N <= 1e5 superheroes with powers <= 1e5. In an operation we can remove one superhero (if at least two) or increase the power of one by 1. We can do at most M <= 1e7 operations and at most K on a specific superhero. We want to maximize the average power.
Notes:
1/ We test every amount of removals. We remove 0, 1, 2, etc. We remove the smallest and see how many ops we can use for the remaining gain. 2/ I think we can binary search on a max average too, removing anyone below that average and incrementing the rest, but not sure if this works with the K per superhero cap?
Solutions:
A. Superhero Transformation
Problem Summary:
We have S <= 1000 length string and T <= 1000 length. We want to transform S into T. We can change any vowel in S to any other vowl, and any consonant in S to any other consonant. Can we do it?
Notes:
Wording is unclear, so a->e and a->i are both possible at different positions. becomes trivial
Solutions:
A. False Alarm
Problem Summary:
We have N <= 10 doors and we want to pass through all of them, some are open and closed, if open we can pass in 1 second. Cannot pass through closed doors but we can use a special power once which makes all doors open for X seconds. Can we pass?
Notes:
Find leftmost and rightmost closed and see if it is small enough
Solutions:
B. Shrink
Problem Summary:
Construct a permutation of size N <= 2e5 where we can do this operation the max # of times: -pick a non endpoint number that is bigger than its neighbors, remove it
Notes:
Put 1 and 2 on the ends now the max can always be removed
Solutions:
C. Cool Partition
Problem Summary:
We have N <= 2e5 numbers <= N. We want to partition it. A partition is cool if for each segment b_j, all elements in b_j also are in b_j+1. So [1, 2] [2, 3, 1, 5] would be good. Find the max # of segments we can make.
Notes:
Observe the last segment must contain every number, I went right to left, my logic is a bit confusing in hindsight I think there might be some better ways with like distinct_prefix counts
Solutions:
3596. Minimum Cost Path with Alternating Directions I
Problem Summary:
We have M, N <= 1e6 rows and columns in a grid. The cost to enter (i, j) is (i+1) * (j+1). We began at 0,0. On odd moves we must go right or down, on even moves we must go left or up. Find the min cost to reach m-1,n-1 or -1 if impossible.
Notes:
It's basically almost ways impossible, I just did casework
Solutions:
3328. Find Cities in Each State II
Problem Summary:
Given a SQL table of cities find all cities in each state that have at least 3 cities, one city which starts with the same letter as the same
Notes:
Subquery where I aggregate cities together, get the count, check how many equal the state letter with SUM(CASE ...), then another query outside it
Solutions:
1577. Number of Ways Where Square of Number Is Equal to Product of Two Numbers
Problem Summary:
We have two arrays of length <= 1000 with numbers <= 1e5. Find the number of triplets (i, j, k) where nums1[i]^2 == nums2[j] * nums2[k], and the same for the other direction
Notes:
We can solve each array orientation separately. Many ways: 1/ O(n^2) For a number in nums1, loop through all numbers in nums2, find the other factor, get a count with a counter. Or loop on pairs and multiply them and look up the square in the other array. 2/ O(n * pollard rho on square) For a number in nums1, fast factorize the square with pollard rho, enumerate all D divisors and look them up in a counter in nums2 3/ O(n * d of square) For a number in nums1, fast factorize it, generate all factors of square by doing like (p1 * e1) -> (p1 * 2*e1) and generating the list, then look up LET'S UNDERSTAND POLLARD RHO AND FACTORIZATION TECHNIQUES: For a number N there are several sizes to keep straight: N - the value numDistinctPrimes(N) - the # of distinct prime factors, like 12 = 2^2 * 3 which has 2 distinct ones numPrimesWithMult(N) - # of prime factors multiplicity allowed, so 12 has 3 numDivisors(N) - just the number of divisors, so 6 numDistinctPrimes <= numPrimesWithMult <= log2(N) The first is obvious, the second is because all primes are >= 2 so it would grow faster numDivisors can be larger than logN but it grows slowly, for example N <= 10^10 has max divisors 6720 Pollard Rho: It is a randomized alg. Given a composite N it gives some non trivial factor d (1 < d < N) in N^1/4 per call expected, or N^1/4 * logN not fully sure on this We can use deterministic Miller-Rabin to check if prime in k log^3 N time where K=7 for 64-bit numbers. But since N is a 64 bit number two of those log factors are actually O(1) machine operations so we get k time logN, which is 7 log N. <-- also not 100% on these ideas So the full flow is something like this?: function fullFactor(N): if N == 1: return {} if isPrime(N): # Miller-Rabin return {N: 1} d = pollardRho(N) # some factor, 1 < d < N left = fullFactor(d) right = fullFactor(N // d) return merge(left, right)
Drill Type:
Mindsolvere-read notes
Solutions:
855. Exam Room
Problem Summary:
We have N <= 1e9 seats that are all empty. When a student enters a room they want to sit as far as possible from other people, if a tie, they sit at the leftmost index. If no one is in the room they sit at position 0. Also support leave(i).
Notes:
Let us attempt to just store the free ranges in a SortedList, like ([0, n-1]). The issue is we need sizes too, as we must pick the biggest size. So we have a second sorted list holding sizes, like (size, left, right). But that sizes one is not enough because when they leave we need to find the interval they are in, so we need both. In general we can find the biggest size, place them in the middle, and handle the logic. But there's some edge notes: 1/ if empty we place at 0 -> can just code this logic in, check if we are fully empty e.g. we have one full range interval 2/ edge ranges like [0, 3] being free, despite being smaller, can score more than larger regions in the center like [15, 20] since placing someone at an edge puts them the full distance away, not a midpoint distance. To fix this, I found simplest way was to have all the bySize sorting assume we place in the middle and get that score, and in the seat() function we check the leftmost and rightmost intervals by position, see if they are at the edge, and theorize what we would score. Helpful to make helper functions like rem(l, r) and such This makes logN for everything
Drill Type:
Mindsolvere-read notes, clean handling with helper functions and clean logic to deal with sitting at ends vs sitting in the middle, just always assume the sorted list sits us in the middle and check ends separately
Solutions:
1722. Minimize Hamming Distance After Swap Operations
Problem Summary:
We have two arrays source and target of length N <= 1e5 containing numbers. And a list of E <= 1e5 swaps (a, b) which means we can swap source[a] and source[b]. Find the minimum # of differences between source[i] and target[i] we can make after any amount of swaps
Notes:
1/ Gather components 2/ In a component, we can re-order those numbers however we like 3/ See how many elements we can match with those numbers from target
Solutions:
829. Consecutive Numbers Sum
Problem Summary:
Given N <= 1e9, find the # of different consecutive positive sequences that sum to N
Notes:
Answer for a sequence of length 1, 2, 3, etc - we can sum 1...X and then check the remaining required values. This terminates at rootN since the sum grows squared.
Solutions:
213. House Robber II
Problem Summary:
We have an array of houses with money and can steal but not from 2 adjacent, and it is circular, max money?
Notes:
We could try two options including the first index and not last, or vice versa, or add another state
Solutions:
171. Excel Sheet Column Number
Problem Summary:
Given a column in excel like "ZYA" find its number
Notes:
Basically base 26, loop and multiply
Solutions:
175. Combine Two Tables
Problem Summary:
Given a SQL table of people and addresses basically combine them
Notes:
just a JOIN
Solutions:
181. Employees Earning More Than Their Managers
Problem Summary:
Given a SQL table of employees find those who make more than their managers
Notes:
Join and compare
Solutions:
183. Customers Who Never Order
Problem Summary:
Given a SQL table of Customers and Orders find customers who never ordered anything
Notes:
JOIN and then select from that
Solutions:
198. House Robber
Problem Summary:
Houses have money, we cannot rob two adjacent, get the most money
Notes:
standard dp, can do bottom up space optimized
Solutions:
199. Binary Tree Right Side View
Problem Summary:
Get the right side view of a binary tree
Notes:
Either bfs and use the last node, dfs and track our position and update, or bfs right to left and use the first
Solutions:
202. Happy Number
Problem Summary:
We are given N < 2*31, find if it is happy. Take N, replace it with the sum of the squares of its digits, if it hits 1 (it stays there) it terminates, otherwise it is not happy
Notes:
At most a transformation turns a number of N into 9^2 * logN so I guess, I don't actually know a proof of the upper bound complexity of this but we see it reduces quickly, so we could just simulate it and hash set We could slow and fast pointer too to see if it has a cycle but do O(1) space There was some analysis about finding the biggest number with a next bigger value is 243 so any cycle must contain numbers smaller than 243 or something and we can deduce the finite list of cycles and use that
Solutions:
206. Reverse Linked List
Problem Summary:
reverse a linked list
Notes:
iterative with prev is best
Solutions:
203. Remove Linked List Elements
Problem Summary:
Given a linked list and an integer, remove all nodes that have that value
Notes:
standard linked list, dummy node, etc
Solutions:
200. Number of Islands
Problem Summary:
Given a binary grid find the # of islands
Notes:
we can dfs, bfs, or union find
Solutions:
182. Duplicate Emails
Problem Summary:
Given a SQL table of emails find all duplicates
Notes:
GROUP BY HAVING count
Solutions:
170. Two Sum III - Data structure design
Problem Summary:
Design a data structure which supports add a number, and find(value) returns a boolean if any two numbers sum to value
Notes:
Don't think we can do better than O(n) find, either using a hashset or a SortedList and the sorted two sum, but that requires logN add (idk why I did it like this)
Solutions:
169. Majority Element
Problem Summary:
Given N <= 5e4 numbers find the majority, it always exists
Notes:
Giving a 3/10 difficulty for boyer moore version
Solutions:
150. Evaluate Reverse Polish Notation
Problem Summary:
Given a string of tokens like ["2","1","+","3","*"] evaluate it in reverse polish notation, hard to describe but could look at code
Notes:
Basically stack, when we hit an operator process it on the last 2 elements
Solutions:
145. Binary Tree Postorder Traversal
Problem Summary:
Given a binary tree get its postorder traversal
Notes:
postorder dfs
Solutions:
144. Binary Tree Preorder Traversal
Problem Summary:
Given a binary tree get its preorder traversal
Notes:
preorder dfs
Solutions:
141. Linked List Cycle
Problem Summary:
Given a linked list, determine if their is a cycle in it
Notes:
Slow and fast pointer see if they meet
Solutions:
140. Word Break II
Problem Summary:
We have a string S <= 20 length and a dictionary of D <= 1000 words of length <= 10, add spaces to S so every word is in D, find all possible unique sentences. It is guaranteed the answer is <= 1e5 length.
Notes:
We could backtrack, which ends up being 2^n nodes (we put a partition or not between everything), and N work at the end to update the result. We do O(10) hash lookups to check if that word is in the word dict but even if it were O(n) it doesn't affect complexity because if we imagine a tree of 2^n nodes (regardless of for loop backtracking or not) then each node could do N work and not degrade complexity. N * 2^N for backtracking then For dp we have dp(i) is for ... and holds all those answers, for a given DP we loop through 10 sizes and update the result, DP doesn't improve things I think, we still have to generate the entire answer and build it out, since the DP result could be as large as n * 2^n size in a string 'aaaa...aaa'
Drill Type:
Mindsolvereview notes, mostly how DP doesn't actually improve complexity here because we are bounded by the length of the answer, but it's probably better on average, I mean if we have two different prefixes we build like "aa" "b" vs "a" "a" "b" and we can re-use work for the suffix after it, I don't think it matters that that suffix is cached in a DP or backtracked, because worst case the suffix could be a bunch of c's and the size of the cached value is the size of the # of states produced by backtracking
Solutions:
131. Palindrome Partitioning
Problem Summary:
Given S <= 16, partition it such that every substring is a palindrome, find all ways
Notes:
We can loop at an index and check if that substring is a palindrome, I think the complexity does not degrade if we do a naive palindrome check inside the loop, the thought is there are 2^n nodes in a backtrack (Without a for loop) since we either place or don't place a separator between each two letters, and leaf nodes do O(n) work to place the result, so all nodes can do N work? not sure if it really translates though, I mean in the tree with for loop backtracking we still have 2^n nodes, every node should take on a different state uniquely, so doing N work at every node doesn't affect anything
Drill Type:
Mindsolvere-read notes, I think complexity does not degrade with naive check
Solutions:
2117. Abbreviating the Product of a Range
Problem Summary:
We have left, right <= 1e4. Calculate the product of all those numbers. Remove all trailing 0s. If the remaining number is <= 10 digits, do nothing to that part. Otherwise turn it into <first five digits>...<last five digits>. Add on e<number of trailing 0s> to the end. Return this.
Notes:
First we could try to calculate the product manually without trailing 0s. If it is <= 10 digits we can basically have our answer. To do this, start manually multiplying. However we cannot just keep manually multiplying and stop the moment we hit >10 digits, because some future ending digits might get stripped out due to trailing 0s. Instead lets multiply the numbers together but remove all their factors of 2 and 5. We terminate if the product is >10 digits. Now multiply by the remaining 2s and 5s factors that didn't produce trailing 0s and again check if we exceed 10. If we don't then we just take this final product + number of trailing 0s. If we do exceed 10 we need the last 5 and first 5 digits. Last 5: We could literally just track the product of the last 5 digits before any trailing 0. Multiply all numbers together, every number strip all trailing 0s, throw away anything above 5 digits. Remember to add on a 0 at the beginning like if we trail with 8192 we actually trail with 08192 at the end. First 5: One idea, we can actually do the same thing. Store the first 18 digits, multiplying each number and dropping digits off the end. Now we keep the top 5. We use 18 for more precision but I didn't precisely follow the math. This worked for me though. Another idea (which had precision issue in a test case, then I tried decimal but it TLEd): # any positive number P can be written in scientific notation P = m * 10^k # m is the mantissa and satisfies 1 <= m < 10 # EXAMPLE: # P = 7,219,856,259,000 # P = 7.219856259 * 10^12 # m = 7.219856259, k=12 # the leading digits of P come from P # take log_10 of both sides # log_10(P) = log_10(m * 10^k) # log_10(P) = log_10(m) + log_10(10^k) # log_10(P) = log_10(m) + k # since 1 <= M < 10, we know log_10(m) is in the range [0, 1) # and K is an integer # log_10(P) will then be some integer portion + fractional portion, remember log_10(P) is kind of like the # of digits of P # log_10(m) will be the fractional portion, and K will be the integer # we want to solve for M # log_10(m) = fractional part # m = 10^(fractional part) # now we compute log_10(P)
Drill Type:
Mindsolvere-read notes
Solutions:
848. Shifting Letters
Problem Summary:
We have a string of N <= 1e5 letters and N shifts where shifts[i] means we shift the first i+1 letters forwards by that much (wrapping z->a), find the final string
Notes:
I did a sweep line version but I think something about a suffix sum works or also looping backwards for O(1) space
Solutions:
1324. Print Words Vertically
Problem Summary:
We have strings like this, we want to print it vertically Input: s = "TO BE OR NOT TO BE" Output: ["TBONTB","OEROOE"," T"] Explanation: Trailing spaces is not allowed. "TBONTB" "OEROOE" " T"
Notes:
Find the max word length, loop over that, loop over each word
Solutions:
1247. Minimum Swaps to Make Strings Equal
Problem Summary:
We have 2 strings of length <= 1000 with only X and Y, like s1 = 'xx' s2 = 'xy', in an operation we can swap any digit from s1 with any from s2, min # of ops to make them equal, or -1 if impossible
Notes:
Note this configuration: XX YY Requires only 1 swap to become YX YX So we count XY and YX pairs. Each one contributes the floor of half of it to the final score. Like 2 YX pairs YY XX Contributes score 1 Obviously we ignore already matched pairs like: X X Now if we have something like XY YX We can fix this in two operations: YY XX -- XY XY But we basically only do this once, cause if we had 2 of those, we would have two XY and two YX which we fix in 2 total operations Only issue is if we had a single XY or single YX we cannot repair that, but we check that total Xs and Ys are both even and things work out
Drill Type:
Mindsolvere-read, don't need to solve super in depth but just feels like one of those patterns that comes up a bit
Solutions:
524. Longest Word in Dictionary through Deleting
Problem Summary:
We have a string S of length <= 1000 and D words <= 1000 (each word also <=1000 length), find the longest of the D words that is a subsequence of S, if multiple possible give the smallest lexicographical one
Notes:
No better way than to manually check, note that to avoid the sorting of D words (as we want a lexicographical answer) then we could just maintain our best answer, and for each word compare it against our best, capped at the length of the current best and the word we consider, which does not affect asymptotics
Drill Type:
Mindsolvekind of a cool idea to avoid sorting
Solutions:
531. Lonely Pixel I
Problem Summary:
We have a grid of B and W cells, find the number of lonely black cells, a cell is lonely if that row and column don't have others
Notes:
Keep a counter for each row and column
Solutions:
515. Find Largest Value in Each Tree Row
Problem Summary:
Given a binary tree find the largest value in each row
Notes:
Can dfs or bfs
Solutions:
463. Island Perimeter
Problem Summary:
We have a matrix grid of water nad land, there is one island, find its perimeter
Notes:
For all land cells, look at all the sides
Solutions:
433. Minimum Genetic Mutation
Problem Summary:
Genes are 8 letters and consist of A C G T. We have a start and end gene and a bank of genes. We want to go from start to end using only bank genes, find the min length path
Notes:
standard bfs
Solutions:
434. Number of Segments in a String
Problem Summary:
Given a space separated string find the # of words
Notes:
can do O(1) space by looping
Solutions:
436. Find Right Interval
Problem Summary:
We have an array of N <= 2e4 intervals [start, end] with coordinates >= -1e6 and <= 1e6, all starts are unique. The right interval for an interval i is another interval j where start_j >= end_i and start_j is minimized, find the right interval for all i.
Notes:
Basically for each interval we need to find the smallest start value that is >= our end, so we sort the intervals and binary search for start points someone also did a two pointers + sorting but I hate those
Solutions:
389. Find the Difference
Problem Summary:
We are given S and T, T is S shuffled with an extra letter, find that letter
Notes:
two counters
Solutions:
388. Longest Absolute File Path
Problem Summary:
We have a file system storing both files and directories, using \n and \t to help a string basically form the shape of the directory, find the longest length absolute path
Notes:
We can basically use a stack and check the length of it, a lot of annoying indexing / math
Solutions:
381. Insert Delete GetRandom O(1) - Duplicates allowed
Problem Summary:
We need to support a data structure with O(1) average insert, delete, getRandom, and duplicates are allowed - random chance should relate to the % frequency of that element
Notes:
Standard easier version of the question, we maintain a counter of elements and an array, to insert we update both, get random picks a random one from the array, and to delete we look up the number in a num->list of indices map, look at the last index in that bucket (since O(1) to pop from it), swap with the ending element, and update the maps, think this should work For some reason in my initial submission I did a lazy delete, so I tracked lazy removals and when I call get random and it hits something with lazy removals I then delete it, I guess this is O(1) amortized but just seems weird
Solutions:
380. Insert Delete GetRandom O(1)
Problem Summary:
We need to support a data structure with O(1) average insert, remove, getRandom, no duplicates allowed.
Notes:
We maintain a set of elements and a list. And a map of element -> pos in list. Insert and getRandom are then easy. To remove, find that element, swap to the end, and pop.
Solutions:
348. Design Tic-Tac-Toe
Problem Summary:
We have an NxN board and we need to design tic tac toe which supports move operations and tells us if there is a winner after that move
Notes:
When we place a move we can linearly iterate, but there is even an O(1) approach per move Since we only win when we get N marks in a row/col/diag we can just maintain a counter for each of those
Drill Type:
Mindsolvereview notes because second part is genius
Solutions:
350. Intersection of Two Arrays II
Problem Summary:
Given two arrays, return an array of their intersection but numbers appear based on the # of times they appear in the originals
Notes:
Two counters
Solutions:
349. Intersection of Two Arrays
Problem Summary:
Given two arrays, return an array of their intersection
Notes:
Two sets
Solutions:
318. Maximum Product of Word Lengths
Problem Summary:
We have N <= 1000 words of lengths <= 1000, find the max len(word1) * len(word2) where those words share no common letters.
Notes:
For each pair we check if they share letters, we precompute the set of letters and do a set intersection, or a bitmask for a single machine op
Solutions:
305. Number of Islands II
Problem Summary:
We have a binary grid of 1s and 0s representing land and water, we can perform a single add land operation turning water -> land, for each position in the grid, find the # of islands if we turned that into land
Notes:
Union find and now we know which of the 4 adjacent neighbors are connected, we could assign an ID to each node or I think easiest would be to just query the parent of each adjacent 4
Drill Type:
Mindsolvere-acknowledge note we don't need an idx, we can just check parent reps
Solutions:
307. Range Sum Query - Mutable
Problem Summary:
We have an array of nums and point updates and range sum queries
Notes:
Standard seg tree or sqrt decomp
Solutions:
293. Flip Game
Problem Summary:
We have a string of only + and -. We take turns flipping ++ into --, the game ends when the other person cannot make a move. Return all possible states after one valid move.
Notes:
Just enumerate all moves
Solutions:
286. Walls and Gates
Problem Summary:
We have an MxN (M,N <= 250) grid of walls, empty rooms, and gates. For each empty room find its distance to the nearest gate.
Notes:
Standard multi-source bfs
Solutions:
1747. Leetflex Banned Accounts
Problem Summary:
Given a SQL table of logins, find who should be banned, meaning two IPs were logged in at the same time
Notes:
Join the login table against itself querying for matching account ids, different ip addresses, and both logins occured before the other logout (clever)
Solutions:
2388. Change Null Values in a Table to the Previous Value
Problem Summary:
Given a SQL table of drinks replace all null drinks with the name of the previous non-null row
Notes:
This is some classic "forward fill" problem, there are surely better ways but I basically learned about a hidden .ctid field which gives a physical location which I could use
Solutions:
2335. Minimum Amount of Time to Fill Cups
Problem Summary:
We have 3 types of water, cold warm and hot. We want amounts <= 100 of each (different amounts). Every second we can fill two cups with one water, or one cup with one water. Find the min # of time to fill all
Notes:
Say the 3 amounts sorted are A <= B <= C We obviously must take at a minimum C time since we cannot go faster. We also must take a minimum of ceil((A+B+C)/2) time since we cannot subtract more than 2 at a time. The answer is the max of these two. See: If C >= A + B we take C time by pairing C with a and B and then the rest solo deplete C. If C < A + B we always pick the biggest 2, didn't airtight prove this never results in an [X, 0, 0] case though Obviously we can simulate but that is slow
Drill Type:
Mindsolvereview notes
Solutions:
3279. Maximum Total Area Occupied by Pistons
Problem Summary:
We have N <= 1e5 pistons some are moving up and some down, the height at each piston is up to 1e6. As time flows they move 1 unit in their direction, reversing at the ends. Max area under a piston at any point in time?
Notes:
We could imagine a piston's space over time as X, X+1, X+2, ... hits the ceiling, goes back down to 0, then goes back up to X. This space of time is <= 1e6, and we have arithmetic progression range adds. We want the max after. To avoid T log T work to query each point we first push down all nodes in O(T) then we can query each leaf in O(1), so it becomes O(n log T). Other ideas: I believe some sort of version of two sweep lines should work, one for the step value and one for the constant value, I was testing some things with claude and it was pushing back on some of my ideas so I didn't fully explore I think we can consider this as a piecewise function with at most like 2*n breakpoints so there's some geometric intuition We can kind of simulate it at any time we gain the # of up pistons - # of down pistons and move them between two deques at most 2n times I think similarly we could use a heap and poll for things hitting the endpoints and bookkeep the # of up and down
Drill Type:
Mindsolvere-read notes
Solutions:
Polynomial Queries
Problem Summary:
We need to support range add in a...b 1, 2, 3, and so on. And range sum queries.
Notes:
It is an arithmetic progression segment tree. We can represent a lazy addition of (coefficient, constant) so if a node covers a range i...j and we have coeff=3 constant=2 it means the i-th element gains coeff*0 + constant, i+1th gains coeff*1 + constant, and so on We can compose these together just by adding the lazy coefficient with the new coefficient, and same for the constant factors also some sqrt decomp idea
Drill Type:
Mindsolvereview
Solutions:
3906. Count Good Integers on a Grid Path
Problem Summary:
We have two numbers L and R <= 9e15, and a string directions of length 6, basically we need to count # of numbers in the range L...R that follow this weird rule set, best to read the original problem
Notes:
Best is to precompute all the notable indices of the initial digit and then do dp(i, ltight, htight, prevDigit, notableI). I initially had a weirder implementation where I kind of rolled up the (r, c) logic inside the DP but I couldn't debug, realized my mistake was not considering the initial 0,0 cell as special, it's one of those things where I was sort of conflating the concept of entering a recursive call with the prior parameters
Drill Type:
Mindsolvere-read notes first to remember the precompute special indices is better, stop and think clearly during contests, I guess mostly just that because it helps me not run into that annoying state / previous call / current call issue, but really the problem point was here: for d in range(low, hi + 1): ndigit = prevDigit if not isNext else d isNext wasn't being set to true in the first 0,0 call to my dp function which caused problems, because really what I wanted was "isImportant" not isNext
Solutions:
3905. Multi Source Flood Fill
Problem Summary:
We have an MxN grid (M*N <= 1e5) and some set of initial cells with colors, every second they expand, and a cell becomes the max of the new flood-fill if multiple cells reach a new one at the same time, return the final grid
Notes:
Standard bfs but we have to allow multiple on a layer to overwrite, I did this by using both a seen and an lseen set I'm sure there's other ways. Lee also did some BFS but sorted by larger values first which I think simplifies it
Solutions:
3904. Smallest Stable Index II
Problem Summary:
We have N <= 1e5 numbers <= 1e9, find the earliest index i where the prefix sum - postfix sum is <= K <= 1e9
Notes:
prefix/postfix, I did sparse table since I was in contest
Solutions:
3903. Smallest Stable Index I
Problem Summary:
We have N <= 100 numbers we want to find the earliest index where the prefix sum - postfix sum is <= K <= 1e9
Notes:
Prefix/postfix, I used sparse table since I did it in contest
Solutions:
1778. Shortest Path in a Hidden Grid
Problem Summary:
We have an MxN (M,N) <= 500 grid with a start and ending position, and some walls. We don't actually know the grid, we are given a class which we can tell if we can move a certain direction, if we are current on the target, and the ability to move our robot. Find the min distance to the target.
Notes:
PROBLEM: We have 1 robot only, so a BFS becomes untenable. We dfs to find the target, using a seen set to keep it O(m*n), and we don't terminate early when we hit the target, we enumerate all cells. Now in step 2 forget about the robot, seen cells indicate open cells. Run a standard BFS.
Drill Type:
Mindsolvere-mindsolve
Solutions:
577. Employee Bonus
Problem Summary:
Given a SQL table of employees and bonuses get all employees who didn't get a bonus or got one <1000
Notes:
just left join
Solutions:
594. Longest Harmonious Subsequence
Problem Summary:
Given an array of N <= 2e4 elements find the longest subsequence where the difference between the max and min is exactly 1
Notes:
Check all pairs of number types (using the sorted array)
Solutions:
590. N-ary Tree Postorder Traversal
Problem Summary:
Given an N-ary tree, get the postorder traversal
Notes:
just postorder dfs
Solutions:
589. N-ary Tree Preorder Traversal
Problem Summary:
Given an n-ary tree, get the pre-order traversal
Notes:
just preorder dfs
Solutions:
593. Valid Square
Problem Summary:
Given 4 points, determine if they form a square
Notes:
Check equal side lengths, we can do this by finding the minimum 4 distances between all pairs of points, and the last 2 distances are equal, maybe some other ways too
Drill Type:
Mindsolvere-read notes
Solutions:
573. Squirrel Simulation
Problem Summary:
We have a garden of size height x width (height, width <= 100) where there is a tree, a squirrel, and N < 5000 nuts, the squirrel wants to bring 1 nut at a time to the tree then end at the tree, find the min # of moves it can make
Notes:
Each nut is going to be a tree->nut->tree loop, except for the first which is squirrel->nut->tree, so find the most savings we get for any nut
Solutions:
561. Array Partition
Problem Summary:
We have 2N (N <= 1e4) numbers, group them into pairs (a, b), (c, d), ... such that the sum of the min of each pair is maximized. Return this max sum.
Notes:
We just sort and do it, could bucket sort too
Solutions:
560. Subarray Sum Equals K
Problem Summary:
Find the # of subarrays with sum equal to K
Notes:
Standard lop off method
Solutions:
559. Maximum Depth of N-ary Tree
Problem Summary:
Find the max depth of an n-ary tree
Notes:
just dfs
Solutions:
552. Student Attendance Record II
Problem Summary:
We want to find the # of attendance records of length N <= 1e5, consisting of A P L (absent, present, late) where there was at most 1 absence and at most 2 consecutive late attendances. Find how many valid sequences there are.
Notes:
We can do dp(i, absences, previousLate) for O(n) or use matrix multiplication for O(logN), there are at most 6 states (2 possible absent states, 3 late states) and we can define a 6x6 transition matrix
Drill Type:
Mindsolvere-read, for matrix exponentiation
Solutions:
551. Student Attendance Record I
Problem Summary:
We have a string of A L P (absent, late, present), find if the student wins an award, they had <= 1 absences and never were late for >= 3 days
Notes:
O(n) 1 pass, can optimize out the 3n factor
Solutions:
520. Detect Capital
Problem Summary:
Given a string make sure all letters are capitals, all are not capitals, or only the first is
Notes:
just do what it says
Solutions:
508. Most Frequent Subtree Sum
Problem Summary:
Given a binary tree, find the most frequent subtree sum
Notes:
Global counter, get sums
Solutions:
507. Perfect Number
Problem Summary:
A perfect number is one equal to the sum of its proper divisors, return if N <= 1e8 is a perfect number
Notes:
rootN factorize or O(d) factorize work, there is also some logN euclid-euler proof in the editorial
Solutions:
506. Relative Ranks
Problem Summary:
We have N <= 1e4 unique scores <= 1e6, athletes are placed based on their scores, either they get gold silver bronze or their rank is their placement, return the ranks
Notes:
Just sort
Solutions:
319. Bulb Switcher
Problem Summary:
We have N <= 1e9 balloons all off, every second we toggle every i+1-th bulb, find how many are on at the end
Notes:
Perfect squares have odd divisors, so we can count those in logN by binary searching, "O(1)" with sqrt math, or just rootN by testing increasing sizes
Solutions:
312. Burst Balloons
Problem Summary:
We have N <= 300 balloons and if we pop one we gain nums[i-1] * nums[i] * nums[i+1] coins, find the max # of coins. If an edge is popped then the left or right are an imaginary 1 balloon
Notes:
dp(l, r) and we enumerate the last balloon to pop in that range, if that is the last balloon, then it would be paired with the l-1 and r+1 balloons, why? Imagine we have a problem for l...r, we pick some last balloon, now we recurse to a sub problem, well it is guaranteed the edges of that subproblem were a last balloon from the prior state
Drill Type:
Mindsolvere-read notes, particularly the edge logic of the last balloon
Solutions:
299. Bulls and Cows
Problem Summary:
We have a secret string number (length <= 1000) and we ask our friend to guess. Then we give a hint, the # of bulls (correct position digit) and cows (right digit, wrong position). Given a secret and a guess, return the hint.
Notes:
we could do one pass
Solutions:
303. Range Sum Query - Immutable
Problem Summary:
Support online range sum queries
Notes:
prefix sums is O(1)
Solutions:
289. Game of Life
Problem Summary:
We have an MxN (M,N <= 25) binary grid that follows the game of life. Living cells with <2 living neighbors die, living cells with 2-3 living neighbors live, and those with >3 neighbors die. Dead cells with exactly 3 living neighbors become a live cell. Output the next state.
Notes:
We can do it in-place by using intermediary values to represent "old state was X, new state is Y"
Solutions:
290. Word Pattern
Problem Summary:
We have a string and a pattern, find if the string follows the pattern, basically the pattern maps a letter to an entire word, we need a bijection
Notes:
keep a mapping in both directions
Solutions:
149. Max Points on a Line
Problem Summary:
We have N <= 300 points, find the max # of points that lie on a line
Notes:
1/ O(n^3) for each of n^2 pairs, check all other n points to see if they lie on the same line 2/ O(n^2), for each pair get a slope, ideally using some gcd or reducible thing, track slope -> count
Drill Type:
Implementimplement the n^2 in the cleanest slope method, might have thoughts on this in another problem
Solutions:
139. Word Break
Problem Summary:
We have N <= 1000 words of length <= 20 and need to see if we can form a string S <= length 300 from some arrangement (duplicates allowed) of them.
Notes:
Naive is dp(i) is if we can form i... in S and we loop over up to 20 lengths and check if that word is in the set, could drop a factor of 20 with rolling hashes I think any bitset/aho corasick attempts get worse complexity
Solutions:
132. Palindrome Partitioning II
Problem Summary:
Given a string of length <= 2000, partition it into the minimum # of palindromes, find that #
Notes:
dp(i) is for i..., we test all options, can precompute if substrings are a palindrome with dp there is some clever bottom up way to do O(n) space but we could also just use two rolling hashes for O(1) isPalindrome check with O(n) space
Solutions:
86. Partition List
Problem Summary:
We have a linked list and a value X,t put all nodes < X on the left and others tw on the right, preserving their relative order
Notes:
Split into two sublists then connect them
Solutions:
82. Remove Duplicates from Sorted List II
Problem Summary:
Given the head of a sorted linked list, delete all nodes that have duplicate numbers, slightly different from the first version of the problem where we leave 1 copy of each
Notes:
I'm guessing we can do it in a few ways but I basically checked if this is a duplicate then did a nested walk to find the new point
Solutions:
83. Remove Duplicates from Sorted List
Problem Summary:
Given a sorted linked list remove duplicates
Notes:
Just keep removing while next equals the current one
Solutions:
167. Two Sum II - Input Array Is Sorted
Problem Summary:
We have a sorted list of numbers, find two indices where the sum of numbers adds to a target
Notes:
L=0 R=N-1 and increment or decrement
Solutions:
165. Compare Version Numbers
Problem Summary:
We have two versioned string numbers like 1.2.01.3, compare them
Notes:
Basically split them into groups and compare each group
Solutions:
151. Reverse Words in a String
Problem Summary:
Given a list of space separated words, get a string where the position of the words are switched, so "hi i am ishaan" becomes "ishaan am i hi"
Notes:
O(n) space to reverse a list, O(1) in mutable string is clever - reverse all characters and then for each word reverse them, maybe other ways too
Drill Type:
Mindsolvere-read notes of clever idea
Solutions:
103. Binary Tree Zigzag Level Order Traversal
Problem Summary:
We have a tree and need a level order traversal but each other layer traverses backwards
Notes:
just a variant of bfs
Solutions:
101. Symmetric Tree
Problem Summary:
Determine if a binary tree is symmetric
Notes:
dfs(node1, node2) but the mirroring is weird, we go left on the left half and right on the right half sort of thing
Solutions:
102. Binary Tree Level Order Traversal
Problem Summary:
Get the level order traversal of a tree
Notes:
standard bfs
Solutions:
58. Length of Last Word
Problem Summary:
Given a string of words and spaces get the length of the last word
Notes:
Just loop backwards
Solutions:
119. Pascal's Triangle II
Problem Summary:
Generate the Nth pascal triangle row
Notes:
Basically just build over and over which is n^2, there is also an O(k) version with math, think of it like this: at a given cell at the bottom row, maybe towards the left, we have to move A total moves left and B total moves right which are fixed, so that's like combinatorics of (A+B)!/(A! * B!)
Drill Type:
Mindsolvere-read combinatorics notes
Solutions:
62. Unique Paths
Problem Summary:
We have an N*M with N,M<=100 grid, find the # of unique paths from 0,0 to the bottom right, moving only down or right
Notes:
dp(r, c) works or we can find the # of ways to interleave the sequences of moves, which I think is just the (A+B)!/(A! * B!)
Solutions:
42. Trapping Rain Water
Problem Summary:
We have N <= 2e4 heights and water rains down, falling out the sides. Compute how much water is trapped.
Notes:
1/ We are limited by prefix and postfix min, so use that 2/ Extend to use greedy two pointers for O(1) space
Solutions:
21. Merge Two Sorted Lists
Problem Summary:
We have two linked lists that are sorted, merge them
Notes:
standard linked list merging
Solutions:
18. 4Sum
Problem Summary:
We have N <= 200 numbers with abs(number) <= 1e9, find all unique quadruplets [nums[i], nums[j], nums[k], nums[l]] with i<j<k<l where the numbers sum to 0
Notes:
We can loop on n^2 first pairs then do the sorted 2 pointers method after, O(n^3)
Solutions:
16. 3Sum Closest
Problem Summary:
We have N <= 500 numbers with abs(number) <= 1000. Find 3 distinct indices so the sum of those numbers is closest to target.
Notes:
1/ We can sort and do the two pointers method on the right, decrementing and incrementing L and R pointers if we are too big or too small, O(n^2) time 2/ I think we can do t^2 + n, maybe with binary search also, didn't look into it
Solutions:
15. 3Sum
Problem Summary:
Given N <= 3000 elements, find the number of triplets (nums[i], nums[j], nums[k]) where i!=j!=k and the three nums sum to 0. No duplicate triplets allowed.
Notes:
We can sort and for a first pointer we want to find how many j and k there are, we can do the sorted two pointers method for O(1) space
Drill Type:
Mindsolvere-read notes
Solutions:
126. Word Ladder II
Problem Summary:
We have N <= 500 words with length <= 5, two words are adjacent if they differ by one letter. Output all minimum length paths from beginWord to endWord.
Notes:
We can just naively generate the adjacency list or do it faster with wild cards. A naive thought is we store a list of all paths of minimum length to all nodes, but I think this degrades in time (it MLEd). A more clever thought is each node stores a list of parent pointers that we could visit. At most each node could feasibly store 500 nodes so we get n^2 memory, and the input states the answer is bounded by 1e5 so we know we wont exceed that with our DFS building. I did this with a level-seen set that makes it so multiple things on the same layer able to consider the adjacent node as a possible connection (which we need to build all paths) but I think we could do it without a level seen, see my code At the end we DFS to build out the results backwards
Drill Type:
Mindsolvere-read notes
Solutions:
127. Word Ladder
Problem Summary:
We have N <= 5000 words with length L <= 10. Two words are adjacent if one character differs. Find the min # of moves to go from beginWord to endWord.
Notes:
A naive idea is to, for all n^2 pairs, check if there is an edge in O(L) time by counting the # of mismatches. Now we have a graph with at at most 26 * L * N edges (we cannot reach N^2 edges!) and we BFS on it. But the N^2 * L complexity kills us. So what if we, for a given node, generate 10 wild cards like ABC_EFG. This is done in O(n * L^2) time (or maybe faster with mutable strings?). Now for a given word we look at all L wild cards, and look at all other nodes that had that wild card, and pair them up. We create the same 26 * L * N sized graph but now the construction of the adjacency list was only N * L^2 time, which works.
Drill Type:
Mindsolvere-read notes
Solutions:
391. Perfect Rectangle
Problem Summary:
We have N <= 2e4 rectangles on a plane, find if they form a perfect rectangle with no overlap
Notes:
1/ O(n * log^2 U) we can support 2d range add and 2d range sum using a 2d fenwick tree, so do that to check no overlaps, then standard individual areas added = total area checks. With the 2d fenwick tree we normalize all coordinates to the positive range also. 2/ O(n), clever observation, corner points should have even parities except for the outer 4 corners, this helps us avoid the bad case of the rectangles fitting into an outer rectangle, and areas being the same, but having an overlap and a hole, since the hole region would create odd parities 3/ O(n log n), sweep line of events on x coordinates, each event adds and removes a y-interval range, with careful bookkeepping and an interval tree I think we can ensure full Y coverage
Drill Type:
Mindsolvere-read notes for all, all good ideas
Solutions:
3761. Minimum Absolute Distance Between Mirror Pairs
Problem Summary:
We have N <= 1e5 numbers <= 1e9, we want to find the minimum distance between i,j (i < j) where the reversed nums[i] == nums[j], and we strip leading 0s when we reverse
Notes:
1/ We cant store i-numbers in a hashmap and then at j try to look up which ones reverse into it, for example [1200, 21] at the 21 we would need to look up 12, 120, 1200, ... (I guess technically we could...) Instead I reversed the array so I made it [21, 1200] and now we can reverse the j-numbers and look up the earlier one 2/ Basically functionally the same as 1, but when we get to an i-number, reverse it and store that in the hashmap, now at a j number just look up that number in the hashmap
Solutions:
100. Same Tree
Problem Summary:
Given two trees check if they are the same
Notes:
dfs(p, q)
Solutions:
92. Reverse Linked List II
Problem Summary:
We have a linked list and two values, we need to reverse the left...right positions
Notes:
I used the rev(L, R) where L is the node before reversed range, R is after, R can be null. We use a dummy node too.
Solutions:
90. Subsets II
Problem Summary:
We have N <= 10 numbers, return all subsets but now we can have duplicates in the input and we don't want duplicate subsets.
Notes:
Similar backtracking, either we skip from a list then skip all, or consider a frequency map and choose how many to list
Solutions:
71. Simplify Path
Problem Summary:
We have an absolute file path and we need to simplify it, things like getting rid of unnecessary .. in the path
Notes:
We can just use a stack and do it
Solutions:
79. Word Search
Problem Summary:
Given an MxN (M,N <= 6) grid of letters find if a word <= 15 letters can be formed from a path
Notes:
Backtrack starting from each cell
Solutions:
78. Subsets
Problem Summary:
Given N <= 10 numbers output all subsets
Notes:
standard backtracking
Solutions:
77. Combinations
Problem Summary:
Given K <= N <= 20 find all combinations of K numbers chosen from 1 to N
Notes:
standard backtracking either with and without a for loop
Solutions:
998. Maximum Binary Tree II
Problem Summary:
We have a binary tree constructed by taking in some array (not given to us) and following this procedure: -find the max element, it is the root -the left tree are the elements on the left -the right tree are the elements on the right Now take that hidden input array, add some given value V to the end, we need to output a tree produced by this
Notes:
Two steps: 1/ Go from binary tree -> array This simple recursion looks like it is O(n) but actually it can be O(n^2) worst case if we keep re-adding large arrays, and O(n log n) in balanced cases I think if we appended things to an array it would be O(n), this is literally just a global result and then inorder dfs Now append V to the end 2/ Go from array -> binary tree Find the max, and construct on left and right This is n^2 if the max is at the beginning or at the end always since we do a full scan, if the max happens to be in the middle we do a full scan initially but then split into two evenly sized subarrays and I think it ends up being logN layers of N sized scans so n log n (whereas worst case we keep descending to lopsided size subarrays and now its N scans of size N) If we precomputed maxes with sparse table or something it could be faster, true O(n) construction after n log n preprocessing There is also a true O(n) construxtion using monotonic stack + dfs or something I didn't look into it SOLUTION 2: We just insert into the tree directly which is O(h) time, something about just. walking down the right spine
Drill Type:
Mindsolvere-read notes, particularly about the complexities of things
Solutions:
2074. Reverse Nodes in Even Length Groups
Problem Summary:
We have a linked list, we will treat is as groups of size 1, 2, 3, 4, and so on (up to the last group which may be truncated). Evenly sized groups need to be reversed.
Notes:
Best abstraction I think is to make a rev(pre, post) function which takes in boundary nodes, we need a dummy pre but the post can be null Also the part outside the abstraction I did a bit weird at first trying to sync prev and curr, maybe different ways to implement it but I found just doing curr = prev.next at the beginning to be best
Drill Type:
Implementre implement with my reversing abstraction
Solutions:
2025. Maximum Number of Ways to Partition an Array
Problem Summary:
We have N <= 1e5 numbers, and a K, all abs() <= 1e5. We can change at most 1 element to K, and we want as many partitions of size 2 (meaning split array into 2 non-zero subarrays) with equal sums. Find the max possible.
Notes:
No change case is easy For a change case, we can check each element, we change it from some old value to K, accounting for a difference. I now want to see any prefixes that start >= i (so our changed point goes in the left) and ones that start < i (our changed point would be in the right subarray). We can basically just use prefix/suffix hashmaps for O(1) frequency lookups, not too bad there was some binary search solution didn't look into it but seemed worse
Drill Type:
Mindsolvere-read notes, maybe peek at code
Solutions:
1243. Array Transformation
Problem Summary:
We have an array of N <= 100 elements <= 100, if a number is a local peak or a local valley it changes by 1, return the final array
Notes:
Naive simulation works, can do O(1) space since as we scan left to right we only need the previous value There is a faster n * log solution I saw but didn't understand it
Solutions:
1206. Design Skiplist
Problem Summary:
Design a skip list (the stacked layer of linked list things) that supports add, remove, and search in logN
Notes:
Alex wice has a really clean implementation that re-uses an iter function Quick reminder of how a skiplist works: -We have different layers, I picked an amount such that it would never have a 0.5 coinflip N times in a row. So for instance 32 height was VERY safe for n = 5e4 adds. We never expect any node insertion to win heads 32 times in a row. Because we randomly flip to decide a level. This gives the natural layering of a bottom level with every node, the first layer with half the nodes, second layer with a fourth, and so on -Think of the top layers like express lanes, we start at the top and zoom right until we must drop down -To drop down we actually just re-use the same node and each node has a forward array for each # of levels it supports -To search, start at the top, walk right as much as possible, then down, repeat, don't worry about the implementation too much -To add, basically we need to find insertion points at every layer, I did it with an "updates" array -Delete is more complex because if we have multiple elements with the same value we need to make sure we don't just delete that value per row, but the actual same true node, you can reference the notes in my code which gave a diagram of a tricky case (thanks to claude) but in short it functions similarly to delete
Drill Type:
Mindsolvejust a mental re-note of how skiplists work
Solutions:
1744. Can You Eat Your Favorite Candy on Your Favorite Day?
Problem Summary:
We have N <= 1e5 types of candies each with a count <= 1e5. We have Q <= 1e5 queries (favorite candy type, favorite day, daily candy cap). We begin eating candies on day 0, following these rules: 1/ At least one candy must be eaten per day 2/ We must finish all candies of type i before i+1 3/ We can eat many types in a day provided rule 2 is followed 4/ We cannot eat more candies in a day than the given daily cap, for the query For each query, can we eat our favorite candy type on our favorite day?
Notes:
1/ binary search O(n log n) For a given query we want to know what's the leftmost day (basically if we eat as slow as possible) we can eat the preferred type, and the rightmost day (we eat the cap per day), and see if our favorite day falls in that range We do this with two binary searches + prefix sums, the indexing was a bit weird, also note the edge case where our binary search value could stay None implying there were more candies than days 2/ O(n) Flip the problem, instead for the given candy type look up the range of candy quantity we can eat and have that type, sort of like a prefix, then look at the range of smallest candy number we can eat (1/day) and max we can eat (cap/day) and see if these two intervals overlap
Drill Type:
Mindsolvere-read, #2 solution is clever and #1 indexing was weird for binary search
Solutions:
888. Fair Candy Swap
Problem Summary:
Alice and Bob have candies that are numbers, we want to swap 1 candy between alice and bob so they have the same weight, find a pair (guaranteed one exists in the inputs)
Notes:
Basically we find the current alice surplus then half of that is the diff and we use that
Solutions:
1256. Encode Number
Problem Summary:
We have a special table of secret encodings for n=0,1,2,...7, given n <= 1e9 deduce the output
Notes:
n+1 in binary, then remove the top bit
Solutions:
3141. Maximum Hamming Distances
Problem Summary:
We have M <= 17 and <= 2^M numbers (roughly 1e5) all <2^m. We want to, for each number, find the max hamming distance between it and any other number.
Notes:
Finding the max hamming distance from X to another number is like finding the min hamming distance from complement(X) to another number. We begin a BFS from all numbers in the array on a graph with all [0, 2^m] numbers in it, seeing how far each number in that range needs to travel to reach a number in our input. Now for each number in nums, we can check its complement, and the min hamming distance to some number in nums. The result then becomes m-minDist[complement]. There was also some DP I did not look into. Also note a trie won't work that degrades to N time
Drill Type:
Mindsolvere mind-solve, noting the concept of hamming weights being invertible, and the right way to do a multi-source bfs (we start from numbers in nums)
Solutions:
3153. Sum of Digit Differences of All Pairs
Problem Summary:
We have N <= 1e5 numbers <= 1e9 all the same length. The digit difference of two numbers is the # of positions they have a differing digit in. Find the sum of all digit differences between all pairs.
Notes:
map[digitPos][digit] -> count and update Think we could also get all the counts up front and kind of do combinatorics from there
Solutions:
2659. Make Array Empty
Problem Summary:
We have an array of N <= 1e5 distinct numbers. In an operation if the first element is smallest, remove it, otherwise put it at the end. How many operations to clear the array?
Notes:
1/ seg tree I want to know the index of the minimum which we can find with a seg tree. I have a virtual index to the "head" of the array based on the current rotation. I can count how many operations to cycle to that min. We can represent a deleted hole by setting it to infinity, so we also need to count the # of infinities in between the range. So our seg tree tells us the index of min and the # of infinities in a range, when we delete we assign to an infinity. 2/ sorted list Didn't look into it but I think we can do something loosely the above but with a SortedList 3/ plain sort Also didn't look into it but some tricky sort idea
Drill Type:
Mindsolvere-read notes / re mindsolve
Solutions:
3902. Zigzag Level Sum of Binary Tree
Problem Summary:
We have a binary tree, we need to layer traverse it, on odd layers left to right, even right to left. Each layer has a score which is the sum of nodes but we stop scoring once we hit a node lacking a child. Find the score for each layer.
Notes:
Many ways to do it, I just avoided a deque and used a list directly which I kept reversing, I think we could also just iterate over the list backwards
Solutions:
3269. Constructing Two Increasing Arrays
Problem Summary:
We have two binary arrays of lengths N, M <= 1000. We want the minimum possible largest number in either array. We must replace all 0s with even numbers and all 1s with odd numbers such that no number is duplicated (even between arrays) and they both are increasing.
Notes:
A super naive dp is like dp(i, j, lastInumber, lastJNumber) which was too slow Then I tried something like dp(i, j, lastNumber) and if we place at i then say its parity is even to our last number, that means we must place lastNumber+2, if it isn't even we can place lastNumber+1. This TLEd so it is likely more states than it looks and also looking back I'm not even sure how this worked because what if we last placed a 4 and the parity at i is odd, that means we could potentially place a 3 but we aren't sure? Probably missing something. These were also bad because we carried the last number through the state and then returned it at the end, but we can basically drop a dimension by just making the return value have the number Anyway I found the easiest to implement solution to be bottom up dp for i and j which solves for placing i and j numbers (NOT placing ...i and ...j, usually bottom up is easier this way). And this dp STORES the smallest number for that, so we stuffed it into the return value So dp[0][0] = 0 our single base case, now we loop on states We could have come from i-1 as our last placement and we look up the smallest number in that case and can infer a new placement using that result, same with j I think top down was kind of weird for me because I was solving like dp(i, j) and looking to future states i+1 j+1 but we actually need to look to previous states i-1 j-1, that makes sense because the array gets built left to right so our recurrence relationship should require solving 0...i-1 first, not i+1...n-1
Drill Type:
Implementshould implement to practice the dp actually, like the bottom up indexing, and also reread notes
Solutions:
710. Random Pick with Blacklist
Problem Summary:
We have N <= 1e9 and need to pick a random number from 0...n-1 but we have M <= 1e5 blacklisted numbers. Build the class.
Notes:
We cannot just keep repicking because if we have N = 1e5+1 numbers and 1e5 are blacklisted we will never find it. We also can't prestore the non blacklisted numbers as there are too many. Also we can't binary search for a number, check how many are blacklisted <= it, and then say "okay actually that means we picked this new number", for instance if 5 6 7 8 are all blacklisted and we picked 5, 1 is blacklisted so we actually picked 6, but that means we picked 7, and so on so it degrades in time and also might not even working since all of 5,6,7,8 would map to 9 Two options: 1/ We have some range [0, n-m] which is like the "real" range of indices we could pick from (not exactly numbers). Say we have N=10 but 2 are blacklisted so we want to pick 0...7. We pick a random selection from that say 6. We want the 6th non-hole number. Let's find the smallest X in range 0...n-1 where (X - blacklisted<=X) is 6. Now this equation could evaluate to 6 at a blacklisted number, but that means if we drop X by 1 we drop both X and the blacklisted<=X by 1 changing the output by 0, so finding the smallest just ensures we skip all blacklisted ones. This is logN * logB time 2/ Split the universe into two ranges 0...m-1 and m...n-1 some numbers in 0...m-1 might be blacklisted, these are holes, we can't pick them (there could also be blacklisted ones in region 2, sure, but not the point) for every blacklisted number in region 1 there is an un-blacklisted number in region 2 consider numbers 0...999 with 20 blacklists so if all 20 are blacklisted in 0...979 then all 20 in 980...999 are free if 5 are blacklisted in the left, 5 are free in the right so we're just going to pick any number in region 1 and if it's blacklisted it gets mapped to a free one in region 2 So it's O(1) pick after O(B log B) (I sorted, think we can avoid) preprocess but note we have to be a bit careful with our looping / construction to not accidentally loop over N or N-B in any way
Drill Type:
Mindsolvere-read notes for both solutions and code for the remapping version since I accidentally had some bad loops the first time I did it, also note I sorted blacklist which allowed me to safely just assign every blacklisted value -> some right position, including blacklisted ones in the region m...n-1 which we technically don't need, but if we remove the sort we could avoid this just by skipping those out of range blacklisted ones
Solutions:
798. Smallest Rotation with Highest Score
Problem Summary:
We have N <= 1e5 numbers all < N. A number is good if it is <= its index. We can rotate our array left any amount of times. Find the best rotations index (max score) or if a tie the smallest # of rotations needed.
Notes:
A number X is good in the index range 0...X This corresponds to up to 2 rotations ranges but it's kind of confusing to make that mapping / handle the indexing. But if we use a sweep line on the # of rotations then we can easily handle. Easiest way: First put the element on the back with i+1 rotations., definitely good here See how many more rotations we can allow, this could make this new number > N Mod it by N, now we have some rotation range [A...B] but A could be > B, if so, apply 2 separate sweep line adds
Drill Type:
Implementresolve because indexing was hard
Solutions:
1664. Ways to Make a Fair Array
Problem Summary:
We have N <= 1e5 numbers, we will delete one number. If the sum of odd indexed numbers is the same as even ones, we gain a point. How many points do we get across all possible deletions?
Notes:
Prefix/suffix on odds and events, flip the parity for the suffix
Solutions:
1943. Describe the Painting
Problem Summary:
We have an integer number line and N different segments [L, R, V] which describe painting that section with color V. If two paints overlap they form a new paint {V_1, V_2}. We basically want to describe the painting in the minimal form, see the description
Notes:
The notable points are at any painting ending or start, I did the event based sweep line, used a prev tracker and also made sure to skip when the sum was 0 indicating an absent segment
Drill Type:
Mindsolveprob just peek at implementation again since some of these sweep lines get tricky
Solutions:
1882. Process Tasks Using Servers
Problem Summary:
We have N servers with weights and M tasks that each take some amount of time. Tasks are processed one at a time, the first at time=0, second at time=1, and so on. When a task enter the queue the lowest weight server, and if a tie, lowest index, picks it up and completes it in the tasks time. If no server is available we wait until one is. Find the server that processes each task.
Notes:
Basically simulate, we store the available servers sorted by (weight, index) and the ones that get released back into availability in (time, weight, index). Maintain a time variable and use that in the bookkeeping too.
Solutions:
1901. Find a Peak Element II
Problem Summary:
We have an NxM (NxM <= 1e5) grid of numbers >= 0. It is surrounded by a border of -1s. No two adjacent numbers are equal. Find any 2d peak (one that is greater than its 4 local neighbors) in faster than N*M time.
Notes:
The 1d version of this is simple, we search for a point, call the value in that 1d array V. The left value is L and the right is R. If L < V < R then we can safely go right and eventually find a local peak (assisted by the -1 on the edge) If L > V > R we look left If L < V > R then we found the peak If L > V < R then either direction has it This is logN We could try to apply this procedure to every row one at a time, and check if it is a 2d peak, but this fails, there isn't a guarantee that the first peak we find with our binary search is also a 2d peak. Instead think of it like this: We pick some column C and find its MAX manually with an O(n) scan. It's now bigger than top and bottom layers. Call those U (for up) and D (for down). If our element V is > L,R then we find a 2d peak if V < L,R we have a divot and a valid 2d peak is on both the left subgrid and right subgrid if L > V > R we look to the left subgrid to find some 2d peak if L < V < R we look right Basically say L>V>R it is safe to claim there is SOME 2d peak on the left (not necessarily a global matrix maximum). Why? Well L was bigger than V, and L is going to be bigger than anything in our column C too, since V was the max of that column. And no element can be the same as its neighbors, so obviously the global max in the left region is going to be bigger than what is above and below it, and too the left. We are only scared about its right neighbor, which could potentially be on our column C, but it must be bigger than that too because our direct value L was bigger than in, and our left global max is at least as big as that This is like n log m We can also do n+m using some sort of quadtree search I didn't look into it EDIT: navneet made a post about breaking this problem, he talks about the quadtree approach more but also a root(m*n) sample and climb solution: https://www.takeuhigh.org/explore/breaking-leetcode/find-peak-ii/cross-method
Drill Type:
Mindsolvere-read notes
Solutions:
3012. Minimize Length of Array Using Operations
Problem Summary:
We have N <= 1e5 numbers <= 1e9. In an operation we can pick two non-zero numbers and delete them, and add nums[i] % nums[j] to the end. What is the minimum length array we can form?
Notes:
First if we pair A and B and A < B we can do A%B which just deletes those 2 and puts back the A, resulting in deleting B only. We can then delete any number not the minimum. And with minimums we pair them together forming a 0 (potentially leaving one last odd minimum out). But can we do better? If we can form a number less than the minimum we can use that single number to nuke everything else. We can do this as long as there is some number in the array NOT a multiple of the minimum.
Drill Type:
Mindsolvere-read notes just because it's an awesome problem
Solutions:
3092. Most Frequent IDs
Problem Summary:
We have N <= 1e5 operations where we will update the frequency of a given ID by some + or - delta <= 1e5. After each operation, find the max frequency of any ID.
Notes:
SortedList holds (freq, id) we discard old and add new using a hashmap to track id -> freq count
Solutions:
3899. Angles of a Triangle
Problem Summary:
Given 3 triangle side lengths, find if it forms a valid triangle, and if so find the interior angles
Notes:
Law of cosines, it's a 2/10 difficulty if you look up the formula or recently worked in geometry lol
Solutions:
3898. Find the Degree of Each Vertex
Problem Summary:
We have an input graph, find the max node degree
Notes:
Just check each edge
Solutions:
3739. Count Subarrays With Majority Element II
Problem Summary:
We have an array of N <= 1e5 numbers <= 1e9, and a target <= 1e9. Find the # of subarrays where the target element is a strict majority.
Notes:
First turn it into a binary array to simplify, we want arrays where 1 is the majority. We can do lop off method, where the prefix stores the SURPLUS of 1s over 0s. Now we know how many prefixes we can cut off. I used a sorted container. There is some really weird O(n) variant by lee which is essentially my idea but somehow he does O(1) updates and avoids the sorted container, one of those weird tricks I think where if we only do certain operations in certain orders we can leave data stale and allow for O(1) updates: https://leetcode.com/problems/count-subarrays-with-majority-element-ii/solutions/7335037/javacpython-prefix-sum-on-by-lee215-gf47/ There's also some stack idea I did not look into that was O(n)
Drill Type:
Mindsolvere-read solution, I was riffing on ideas in the code and I think a lesson is to explore each idea more because one of them was the right idea I just didn't investigate enough
Solutions:
1199. Minimum Time to Build Blocks
Problem Summary:
We have N <= 1000 blocks each of size <= 1e5. We have a worker who can build a block in its size time, or pay split <= 100 time to divide into two. Once we build a block that worker retires. Minimum time to build all blocks?
Notes:
Same as https://leetcode.com/problems/find-time-required-to-eliminate-bacterial-strains/description/ (and that had worse constraints) so I'm just leaving the notes there. Except someone also listed an n^2 dp for this one, I did not look into it
Solutions:
3506. Find Time Required to Eliminate Bacterial Strains
Problem Summary:
We have N <= 1e5 strains of bacteria that each take <= 1e9 time to kill. A single white blood cell can kill a single strain, then retires. We start with a single WBC. It can split into two in splitTime <= 1e9. What is the fastest we can kill all bacteria?
Notes:
If we binary search on answer we need to know "can we kill all of these in time <= X" We should basically greedily split over and over, but the moment a strain requires an immediate kill, we allocate one of our WBCs to kill it, and not split At most we split logN times since we don't ever need more than N WBCs. And we can simulate basically killing each of the N manually, so the checker function is linear, forming log(max) * N. We can make the checker take log^2 time like this: # Yes, the checker can be O(log² n) instead of O(n). The idea: at each split step (there are at most log n of them), instead of popping strains one-by-one, you binary search on the sorted array to find how many strains are too large to survive another split. # so that would make it log^3 n Note that most solutions are using a heap and no binary search on answer, I think it's some idea of building binary trees and finding the most shallow depth, like if we split then we are bottlenecked by the slowest of the two children, I didn't really explore it. Also this is the same question as 1199 so I didn't write the notes for that here.
Drill Type:
Mindsolvejust re-read notes to refresh idea of the greedy
Solutions:
1168. Optimize Water Distribution in a Village
Problem Summary:
We have N <= 1e4 villages with E <= 1e4 weighted bidirectional edges. Each village has cost to open a well there. We want every village to have water, either via its own well or a connected set of pipes to another well. What is the min cost to supply water to every village?
Notes:
I claim we must fill the cheapest well. If we didn't, that village must get water somehow. It would be part of some component, and one village in that component would supply water. But our well is cheapest, so we could swap that more expensive well for our cheaper one. It is never worse to supply water to the cheapest well. Once we do this, we now add all pipes from the cheapest well to other villages. Since those pipe costs are basically indistinguishable from opening new wells at those locations. We repeat the procedure. I think another way to think about this is to imagine a hidden village 0 which has water and the well costs at other villages are basically pipe costs. Now we just want to find the MST which we can do.
Drill Type:
Mindsolvere-read notes just to keep the idea fresh, but not too difficult
Solutions:
3897. Maximum Value of Concatenated Binary Segments
Problem Summary:
We have N segments where each segment contains a_i 1s and b_i 0s. We want to construct each segment, and then re-arrange them all, to form the largest binary number possible. Return this mod 1e9 + 7. Also the sum of all segments is <= 1e5.
Notes:
Each segment should be all 1s then all 0s. We can sort them by putting segments to the left if they have more 1s. If a tie, fewer 0s goes to the left. Edge case is if a segment is all 1s though, like 11 goes to the left of 11110. Also if A+B is > B+A then we should do A before B. It's kind of similar to jiangly's observation that s1^infinity is < s2^infinity if s1+s2 < s2+s1. Also if we do the A+B vs B+A sort and actually construct those strings in the comparator, the sort time becomes (n+L) log n where n is the number of terms and L is the total length of all terms. After we sort we can find the contribution of each digit using modPow. int function should TLE since I think it degrades to n^2 on large binary strings. There may be a faster way with bitsets or something where we are not bound by L, lakkshyag was looking at some stuff
Drill Type:
Mindsolvere-read notes, mostly: -jiangly s1^inf < s2^inf if s1+s2<s2+s1 -A+B before B+A is a way to sort things -remember sorting time is (n+L) log n
Solutions:
3896. Minimum Operations to Transform Array into Alternating Prime
Problem Summary:
We have N <= 1e5 numbers <= 1e9. In an operation we can increment a number. Find the min # of operations to make all even indices prime and odd indices non-prime.
Notes:
Pre-compute a sieve. We could manually iterate every number and check since prime gaps are small, or binary search to find next prime. We could also precompute with a suffix "next prime" array.
Solutions:
3895. Count Digit Appearances
Problem Summary:
Given a list of numbers, find how many times a specific digit appears.
Notes:
Loop over numbers then strings, or use math
Solutions:
3894. Traffic Signal Color
Problem Summary:
Given a number, print a required string
Notes:
just follow instructions
Solutions:
3235. Check if the Rectangle Corner Is Reachable
Problem Summary:
We are at the bottom left corner of a box in a plane and need to move to the top right corner, but there are N <= 1000 circles on the plane (can be overlapping, outside the box, etc). Can we reach the other corner without getting blocked?
Notes:
In general this is not complex. We can union circles together and see if any chain touches the top+bottom, left+right, top+right, or left+bottom. This is done with union find where we also add a "touches" set per parent component. To check if a circle touches an axis-aligned line segment, we want to compare it to the closest point on the line segment. For instance on the top edge of the box, if we are already below or above it, the closest point is the first one directly above/below us, and we check if our radius is at least that big. But if we are out to the side, like out to the left side, we would compare our distance to the leftmost point on the line segment, which we can find the euclidean distance and compare to radius. Now another issue, normally we union two circles if they touch but we actually only want to union them if they touch INSIDE the box. Imagine something like this: -----\_________/-- | / ( \ | I don't know if this drawing made sense but essentially it's a really big circle at the top and at the right, leaving the top right corner actually accessible. But these circles are big enough they would intersect outside the box. Unioning them would then falsely indicate we have a top+right blocking chain. A proof that we only care about intersection points inside the box is imagine we were walking through a room with big circular floor-to-ceiling walls everywhere. If we got blocked it would either be by a single circle which covers 0,0 or the top right coordinate, which is handled by our union find already saying that chain was found, OR by some point those two walls intersect at. So we actually only need to check the up to 2 intersection points between two circles, not all overlap points. There can be 0 intersecting points if the circles are too far, 1 if the radiuses sum to the exact distance between centers, and 2 otherwise. To find 2 we basically find the chord line, get a perpendicular line, and walk up and down until we hit them, I kind of used a geometry template, it also returned floats so I guess could be imprecise. Only if at least one intersection point is inside the circle then we union them.
Drill Type:
Mindsolvere-read notes, mostly takeaway is the union concept, circle touching line segment, and I guess awareness of two circles intersecting points template
Solutions:
3802. Number of Ways to Paint Sheets
Problem Summary:
We have N <= 1e9 sheets to paint. We also have C <= 1e5 colors where we have for each color c_i <= 1e9 paint meaning we can paint that many sheets. We want to find the # of ways to paint the N sheets, using exactly 2 colors, such that the colors each form two contiguous regions like BBBBRR.
Notes:
Say we have to paint 10 sheets. We consider all colors as if they were the left color (so we won't double count these). Say our color has 5 paint. We want to know how many other colors we could combine this with, but the actual # of combinations. Well some other colors could allow us to use all 1-5 quantities of our left color. For instance if another color had 20 paint we clearly have enough of that to fill out the rest no matter what if we use 1, 2, 3, 4 or all 5 of our left color. We find how many of these colors there are (it's just the # of colors that have >= n-1 paint) and we know we can combine those all with all 5 of our current color. Don't forget to exclude our current color 5 from the count, if 5 happened to be >= n-1, to prevent from pairing it with itself. Okay but what about colors that could only partially pair? For instance if we had 8 of another color, we could use 5, 6, 7, or 8 of it in junction with 5, 4, 3, or 2 of our left color. Well we know the min of another color we require is 5 (to pair with our left color 5) and the max is n-2. We find all the colors that exist in this range 5...9, say we have these other options: 5, 7, 7, 8 All of those form partial pairings with our 5 meaning we can use some quantity of our left color 5, but not all of them. For instance the 7 we could use our left color of 3, 4, or 5. The 8 could use our left color of 2, 3, 4, or 5. The actual amounts of these are just each of those colors, minus 4, and the 4 is derived from the minimum we require of another color (5), minus 1. We use binary search and prefix sums to handle this summing, also remembering to exclude our left color if it happens to fall into that partial l...r range too.
Drill Type:
Mindsolvere-read notes, takeaway is for a color consider how many other colors we can pair it with, do some casework and probably write out cases to get a sense of how the math works
Solutions:
3671. Sum of Beautiful Subsequences
Problem Summary:
We have N <= 1e4 numbers <= 7e4. For any positive integer g, the beauty of g is (g * the # of strictly increasing subsequences with a gcd of g). Find the sum of beauties for all g.
Notes:
We want to know the # of strict increasing subsequences with a GCD of X, for all X. First let's actually find the # of strict increasing subsequences all divisible by X. If we do this for all X, we can do mobius inversion style inclusion-exclusion to convert it to GCD. For a given factor say 5, we will track the # of subsequences all divisible by 5, ending in [5, 10, 15, ...]. Across all factors X this is N log N size total due to harmonic series. We loop over numbers, for each number loop over its factors. Each factor would contribute to a different factor -> dp array bucket. We need to support range sum and point update to update the dp. I used a fenwick tree with the dp array. In total we do n * d * logn work roughly.
Drill Type:
Mindsolvere-read notes, best parts were: -using fenwick tree to ac in python since my seg tree was slow constant factor (probably could be optimized) -maybe re-read the mobius inversion code at the bottom to see how I converted from "divisible by X" -> "gcd is X"
Solutions:
B. Another Problem about Beautiful Pairs
Problem Summary:
We have N <= 2e5 numbers <= 1e9. Find how many pairs (i, j) exist where a[i] * a[j] = j - i
Notes:
Heavy/light query processing: call B the ceiling of the square root of N If a number X is >= B it can only be multiplied by a number <= B. So we could just manually check all the previous indices in rootN time. We also should do a forward pass to look ahead. Note the edge case we don't double count pairs of (B, B). If a number is <B then it could multiply by a number >= B, or one <B. We already did the first case. For the second case we can just iterate on all numbers from 1...B-1 and check, also in rootN time.
Drill Type:
Mindsolvere-read notes to keep idea fresh
Solutions:
3089. Find Bursty Behavior
Problem Summary:
Given a SQL table of posts we need to find all users who had a 7 day period in february 2024 with a posting frequency at least theirs in all of feb 2024
Notes:
A bunch of subqueries to get: -the posts from feb -all 7 day window starting dates with a generator -posts per user per window -average frequency per user in feb -now we combine all of these to find it
Solutions:
3655. XOR After Range Multiplication Queries II
Problem Summary:
We have N <= 1e5 numbers <= 1e9. And Q <= 1e5 queries [l, r, k, v] where for all numbers in range l, l+k, l+2k, ... up to at most r, we multiply that number by v then apply a mod. Find the XOR of all numbers after all queries.
Notes:
For queries with a K >= root(N) it only takes rootN time to apply the updates manually, do so. For other queries, we might have things like [1, 4, 7, 10, ..., 100] which is more than rootN indices to update. Note we have different groups based on the jump size and the residue. So [0, 3, 6, ...] is the same jump size different residue. If we have rootN jump sizes (the small ones) each takes combined N indices so that's N root N. We could map (jumpSize, startingIndex) -> a sweep line of the size of the # of indices in that residue class. Then when we get a query, we use math to apply a mod mult at sweep[l] and a mod inv at sweep[r + 1]. A few notes about this: 1/ We don't need to precompute all the indices for each residue class, rather we can just have the sweep lines. We set sweep lines to all 1s (identity for multiplication). We can use a nested defaultdict(lambda : 1) or actually allocate the 1s. We apply the sweep gain at the corresponding index for `l` in the query, but r is not necessarily where we lose. Cause it might not be part of the residue class. Like go from indices 33 to 50, jumping by 5. We want to apply a sweep loss at 53 not 50. To find this we can take the difference which is 17, floor divide by jump size to get 3, then re-add 3*5 to 33 to get 48 which is the last position we actually gain. Then one more for the loss position (standard sweep line loses at r+1 type of thing). 2/ We could have the map I suggested above (jumpSize, startingIndex) -> sweep line of just those indices, or we could do a map of jumpSize -> sweep line of size N. Basically squishing all the sweep lines together. This was more performant and let me pass in python even though it's the same complexity. It just makes the aggregate trickier at the end. To aggregate we loop over jump sizes and starting indices and basically treat that N sized sweep line as a bunch of separate lines.
Drill Type:
Implementshould re-implement to practice the nested sweep line stuff, some of the index math, and ability to understand the heavy/light child concept
Solutions:
3716. Find Churn Risk Customers
Problem Summary:
We need to find customers that are churn risks which fits several rules, find those customers
Notes:
I think there are better ways but I used a distinct on trick to get the first value from a group (using our custom ordering) which helped
Solutions:
3078. Match Alphanumerical Pattern in Matrix I
Problem Summary:
We have an MxN M,N<=50 grid of numbers and another one of a smaller size of numbers and letters. We want to find if the smaller pattern matches with the larger grid. We require a bijection of numbers<>letters for the pattern.
Notes:
Brute force, check all n*m top left cells and run another n*m sized pattern check. Bijection means we need both mapping directions enforced. Also numbers can be in the pattern instead of letters so handle those separately.
Solutions:
2217C - Grid Covering
Problem Summary:
We have an H,W <= 1e9 grid. We jump right, then down, then right, ... and so on. The grid wraps in both directions. Our right jump is R and down jump is D. D, R <= 1e9. Do we cover all tiles?
Notes:
First the 1D variant. If we jump right by R and the width is W, do we hit everything? One way is to figure out when we first hit 0 again. We do this after lcm(W, R) steps. So width 10 and we jump right by 8, at lcm=40 total steps we return to 0. Divide lcm(W, R) by R to get the # of actual jumps we make. So lcm(W, R)/R is the # of jumps we make before we repeat. This must be = W to work (otherwise we cycle before hitting every cell). This is also transformable: gcd(a, b) * lcm(a, b) = a * b lcm(a, b) = a * b / gcd(a, b) ((W*R) / gcd(W, R)) / R = W W/gcd(W, R) = W gcd(W, R) = 1 I think this is also kind of intuitive, if our jump and width had a shared factor, we could never land on a number not divisible by the factor? something like that. anyway in the 2d variant we have separate right and down requirements to repeat. Say we need 10 right moves to return to column 0, and 8 down moves to return to row 0. We would think we need lcm(10, 8) = 40 pairs of moves to repeat (which is 80 moves). However this is the # of moves to repeat with the *same parity* meaning our first move after 0,0 is going right. We can actually repeat earlier: col0 col1 col2 col3 col4 col5 +-----+-----+-----+-----+-----+-----+ row0 | 0 | | | 1 | | | +-----+-----+-----+-----+-----+-----+ row1 | 3 | | | 2 | | | +-----+-----+-----+-----+-----+-----+ row2 | 4 | | | 5 | | | +-----+-----+-----+-----+-----+-----+ Move 1: right+3 → (0,3) Move 2: down+1 → (1,3) Move 3: right+3 → (1,0) (wraps) Move 4: down+1 → (2,0) Move 5: right+3 → (2,3) Move 6: down+1 → (0,3) ← REVISIT cell 1! Move 7: right+3 → (0,0) ← REVISIT cell 0! Why does this happen? We are revisiting 0,0 but at a different parity (next move will be down). It would take 2x moves to revisit at 0 with the same parity. But the issue is we are going to repeat the same set of cells, so we don't actually see 2*6 unique cells. I believe there is no closed form way to check when we hit 0,0 early but at the wrong parity. Remember when we get the full cycle with our 2 * lcm of both cycles, each step visits a unique STATE, not a unique cycle. A state is (row, col, parity). Two different states can land on the same cell. We also need the independent row and column cycles to enumerate the full width and height. I don't fully get why this is...
Drill Type:
Mindsolvere-read notes, refresh: -how to compute if we loop on a 1d plane -ideas about the 2d variant, like checking the lcm of both individual lcms, times 2, equals a STATE re-visit not a cell revisit don't worry about fully getting it since I can't airtight prove at the time I solved
Solutions:
B. Flip the Bit (Easy Version)
Problem Summary:
We have a binary string of length N <= 2e5 and a single position p. We can flip any range l...r as long as it contains p. Find the min # of moves to make the entire array into the initial value at p.
Notes:
We have a leftmost and a rightmost position number that are opposite from the number at p. We must flip those, inverting everything in-between (including the number at p). Every time we face a different number, we have to invert again. We can combine left and right sections so we take the max of those.
Solutions:
A. The Equalizer
Problem Summary:
We have an array of numbers and take turns removing one from a single number at a time. The game ends when there are only 0s left (if you cannot move you lose). We also have a special power that replaces our turn and replaces every number with K, once. Can we win?
Notes:
either sum of all is odd or sum of n*k is even
Solutions:
Graph Paths I
Problem Summary:
We have N <= 100 nodes on a graph with E <= N^2 directed edges. Find how many paths from 1 to N exist after K <= 1e9 moves.
Notes:
Matrix exponentiation, state is the # of ways to end at each node, sized N, and we transition K times, n^3 log k
Drill Type:
Mindsolvere-mind solve
Solutions:
3540. Minimum Time to Visit All Houses
Problem Summary:
We have N <= 1e5 houses, each house has a distance to go forward to the next house and backwards to the previous. Also the houses are circular. Answer Q queries for the min distance to visit each house in the specified order.
Notes:
We basically walk left or right, check both
Solutions:
3641. Longest Semi-Repeating Subarray
Problem Summary:
We have N <= 1e5 numbers <= 1e9. And K <= N. We want to find the longest subarray length where at most K numbers occur more than once.
Notes:
Standard variable window, shrink while we have too many repeats
Solutions:
3632. Subarrays with XOR at Least K
Problem Summary:
We have N <= 1e5 numbers <= 1e9. And K <= 1e9. Find how many subarrays have an XOR >= K.
Notes:
We can do this with a trie on prefix XORs. A trie is able to tell us, given a value, how many other values in the trie can we XOR this with to get a number >= X. We can also achieve the same complexity solution without a trie. I didn't fully look into the solution, but it is something along the lines of iterative over all log(max) bits, for each bit iterate over all numbers in the array, find some sort of "branching" point where we need a prefix starting with a certain thing, and count those up: https://leetcode.com/problems/subarrays-with-xor-at-least-k/solutions/7270450/iterative-solution-no-trie-by-westxrn-t5rm/
Drill Type:
Implementimplement bit trie with the advanced function required
Solutions:
3893. Maximum Team Size with Overlapping Intervals
Problem Summary:
We have N <= 1e9 intervals from [L, R] <= 1e9. Find the max # of a subset of intervals such that at least one interval intersects with all of them
Notes:
For a given range, we can search how many touch it. Easiest way is to search how many do not touch it (their R is less than our L, and vice versa), so minor inclusion exclusion I think we could do some two pointers with sorting to check as well but not sure
Drill Type:
Implementquickly re-mindsolve and implement using bisects
Solutions:
2069. Walking Robot Simulation II
Problem Summary:
We have a height x width (height, width <= 100) grid. We start at the bottom left as a robot. We need a move(steps) function which moves and if it hits a wall it turns left first, basically walking the perimeter. The # of steps can be big. Also we need to get the position and direction of the robot at various times.
Notes:
Cleanest way is O(1) everything. We track our position as a number along the perimeter. To move we move steps and then mod by perimeter. To get the position we can check if we are on the bottom strip, else right edge, else top edge, else left edge. For direction we could just use where we are too, with the edge case at 0,0 we face right if we just started and haven't moved yet, otherwise we face down
Drill Type:
Mindsolvehonestly the code is clean should look at it
Solutions:
3743. Maximize Cyclic Partition Score
Problem Summary:
We have N <= 1000 numbers all <= 1e9. And K <= N. The array is cyclic. We must partition it into at most K partitions. The score is the sum of max-min for each partition. What is the max score?
Notes:
1/ O(n^3 * k) super naive - TLE A naive version is to try all N rotations. Then for each rotation we can run a dp(i, partitionsTaken) and loop on N future options. This is n^3 * k. 2/ O(n^3) improved DP - TLE We note a better DP than the super naive one is dp(i, partitionsTaken, state). State is 0 1 or 2 depending on if we have scored the +max, -min, or neither. It's sort of like these open-interval DP ideas. But this is still n^3 time. 3/ O(n^2) improved DP + cycle trick - passes We note that our global minimum would only ever need to be on the boundary of a partition. Otherwise we stand to gain no extra minimum if we move past that. Seems a little bit not fully proven to me cause I have some concerns about how the max interacts with that. Also this observation should work for global max. So we do the normal state DP but only on two arrays. 4/ O(n^2 log MAX) alien trick - passes in C++ with bottom up We can alien trick this. We search for the largest y with >= k partitions. Our DP wants to maximize partitions in the event of ties. We update result every binary search loop, not taking the max of the res each time, just overwriting. For a given y then the dp becomes the same dp(i, state) which is O(n). We run this in N rotations. Note our alien trick here also requires an extra case where the natural DP with a given y penalty results in <k partitions. This is acceptable because we can use at most K partitions, so we should accept that answer too. Otherwise no matter the penalty we never find one that uses >= k partitions. 5/ O(n log MAX) alien trick - passes The above but we only run it on two key rotations. 6/ O(n^2 log MAX) alien trick - didn't test We do only the two key rotations but for each one we do the naive dp(i) and loop on N possible J's. 7/ O(n^2 + n k log n) dnc dp - passes in C++ A normal DNC dp on the array should be n*k log n. With n^2 to precompute all the costs l...r for max-min (can avoid this though with mo's trick I believe, or just sparse table and live query). We run this on only 2 rotated arrays. 8/ O(n*k) - advanced DP, passes in Python dp(i, partitionsUsed, state, wrapState). The same but we track the state of the first every partition too, so if we only took +max from there and -min from the end we can coalesce them. Basically n*k*3*3 Also note I think the way I'm doing aliens can be perfectly mirrored: This finds the smallest y where seg <= k. At termination, right is that value. Then res = f(right).val + right * k. It's the mirror of our approach: | | Ours | Theirs | |----------------|----------------------------|-----------------------------| | Tie-break | more partitions | fewer partitions | | Search for | largest y with seg >= k | smallest y with seg <= k | | Binary search | l = 0, r = max | left = -1, right = INF | | Record answer | when seg >= k, move l up | when seg <= k, move right down |
Drill Type:
Implementshould re-read all notes, keys to remember: -cyclic problems often can have some smart rotation -crazy dp idea to track the state and wraparound state -probably re-read the code I wrote in python for dp(i, state) because it felt a bit too simple but worked -re-implement aliens + naive n rotations in C++, can use top down dp(i, state) should pass. Aliens make sure I can implement the dp tiebreaking and the binary search boundaries logically, understand when and how we update result in binary search, and also realize the "at most k partitions" causes a minor difference in how we aliens too
Solutions:
3891. Minimum Increase to Maximize Special Indices
Problem Summary:
We have N <= 1e5 numbers <= 1e9. We want to have the max # of local peaks (0 and n-1 can't be). In an operation we can increase a number. Find the min # of operations to get max local peaks.
Notes:
If N is odd there's only one option for local peaks, at indices 1, 3, 5, ..., so just add those up. If N is even we basically can have a gap of 2 somewhere: # 56 | (97) 40 (79) 74 45 (101) 4 (84) | 102 56 and 102 can't be peaks as they are edges. We need to pick 4 out of the center 8. Also note the gap could go at the start or end, like 56-97 could be a gap or 84-102. We can do knapsack dp(i, skippedBool) and either we take and go to dp(i + 2, skippedBool) or we skip once and go to dp(i + 1, True) which feels a little bit too simple but it works. Just look at code and think about this skip concept. In contest I did it with a prefix and suffix though. pref[i] is we take i, i-2, and so on. suff[i] is we take i, i+2, and so on. Now I loop over all gapIndex positions. But not we can't start the gap at i=1 or i=n-3 because that would be like 56-97-40 is a gap which we cannot do.
Drill Type:
Mindsolvere-read notes, I guess idea of the knapsack dp actually working and being elegantly simple, also be more careful cause in contest I assumed the gap could only go in two places but it can go anywhere
Solutions:
3892. Minimum Operations to Achieve At Least K Peaks
Problem Summary:
We have N <= 5000 numbers with abs(num) <= 1e5. The array is circular. In an operation we can increase a number by 1. We want to find the min # of operations to get K <= N local peaks (0th and last index wrap around for their peak checking). A peak is strictly greater than both neighbors. Or return -1 if not doable.
Notes:
dp(i, peaksLeft, didIncrementFirst) is n * k * 2. Worked top down in C++. We can optimize space by dropping the n dimension but it's annoying. We have two dp arrays to track and we need access to the previous 2 layers. Easiest way might be to use the mod trick lakkshyag talked about. Like the "rolling" trick to re-use dps. And instead of two arrays for didPickFirstIndex and didn't, maybe just combine everything. But still seems annoying to implement. We could also drop the 2 space dimension by just doing 2 cases, we allow the 0th to be used but not the last, and vice versa. We can also do alien trick in n log MAX. Observe f(k) is the cost to make k peaks. It is concave since each successive peak is at least as bad. Thus we use WQS binary search. Didn't implement or fully investigate. We can also do n log n with a backup algorithm. Didn't really look into this either: https://www.takeuhigh.org/explore/breaking-leetcode/min-ops-k-peaks/greedy-with-undo It uses heaps and a DLL
Drill Type:
Mindsolvere-read notes, and re-read the top down C++ notes here: https://www.reddit.com/user/leetgoat_dot_io/comments/1scxgix/c_dp_ramblings_for_myself/ Pasted here: -global array goes into bss, zero-paging read only, allocation happens only when we try to write at a per-page level. note the 0 page trick only works for globals, on the stack an un-intialized array gets garbage vals -put an array into the function now its on the stack for that fn call = blow up -put a vector, thats fine, only struct goes into stack, big data onto heap -ordering of arrays matter as they are row-major contiguous, put the dimension that moves around a lot at the end. same thing matters with looping orders when we fill out arrays. matters for bottom up, top down to still be discovered -to reset the shared global we can: memset, but takes the entire flat array time loop over only the cells needed in the problem, takes time based on problem inputs use a generation counter, O(1) reset but takes 2n memory -nested vectors screw us. we are making n*m*... new calls which is lots of allocations. every access call is slow because now we're dereferencing multiple pointers. just lots of overhead.
Solutions:
3890. Integers With Multiple Sum of Two Cubes
Problem Summary:
We have N <= 1e9 and need to find how many numbers <= N are the sum of two triple powers a^3 + b^3, with at least two unique combos (a, b) and also a <= b
Notes:
a and b are at most N^(1/3) so loop on those combos for N^(2/3) total time, store achieved numbers in a counter to verify >= 2 combos
Solutions:
3889. Mirror Frequency Distance
Problem Summary:
We have an alphanumeric string of size N <= 1e5. For letters and numbers, find their mirror (a<>z, 0<>9). Sum up the difference in frequencies of these for each mirror-pair, not double counting
Notes:
Just some basic helper functions and then I hashed each pair to not double count like put (a, z) in a tuple sorted alphabetically, but can do it in other ways like loop on only the first half of letters
Solutions:
657. Robot Return to Origin
Problem Summary:
We have a robot making U D L and R moves, determine if it is back at the original at the end
Notes:
Just check U==D and L==R in O(1)
Solutions:
447. Number of Boomerangs
Problem Summary:
We have N <= 500 points on a grid. Find the # of unique tuples (i, j, k) where dist from points[i] to points[j] equals dist from points[i] to points[k]
Notes:
For each point, find its distance to all other points, storing a hashmap of dist -> count. Note we can avoid the sqrt in the euclid distance to avoid root precision, since squared distances that are equal are still the same. I did counts[i][dist] -> # of points that distance away, but we can drop an O(n) storage by just generating the counter inline for each index
Solutions:
1872. Stone Game VIII
Problem Summary:
We have N <= 1e5 stones where each abs(stone) <=1e4. Two players. On a players turn, they select some prefix of >1 stone and pick them all up, adding that sum to their score. They then replace all those stones with a single one equal to the sum of what they picked up, and put that back on the left. The game ends at 1 stone. What is the max (score alice - score bob) we can achieve?
Notes:
A bunch of notes here: 1/ A naive O(2 * n^2) dp is dp(i, isAlice) and we loop through options. A bit of casework with the i=0 case (can't pick up only the first stone at the start) but quite easy. TLEs. 2/ We can improve it to O(4 * n) dp with dp(i, isAlice) and a second cached loop(i, isAlice). NOTE that the base case for main dp is when i==n, return 0. However for the suffix loop we have to return inf or -inf depending on the players turn. We can't just return 0, because that basically implies the player could have just gotten a 0. Like it's a fake escape hatch in the suffix. See code. 3/ We can drop the turn parameter to get O(2 * n) dp with also loop(i) cached suffix. Note we don't need turn params when games are symmetric, e.g. regardless of who they are, they are trying to do the same thing. In this case the DP changes a bit. In the previous 2nd solution since we stored the players turn in the params, when it's alice's turn she is maximizing alice-bob score, when it's bob's, he is minimizing alice-bob. So the dp return alice-bob but the aggregator function changes. In this example though, both players try to maximize my score - other score. So they both apply maximizer functions, we just subtract the next dp. Also note this means the base case for the cached suffix now always returns -inf (again, no 0, because no escape hatch), instead of -inf or inf, depending on the player turn, like we did in code 2. 4/ Now let's do bottom up O(n^2). Which way to we fill out the table? I think it might be easiest to think in terms of top down. In top down, dp(i) depends on dp(i + 1), dp(i+2), and so on. So we fill out from right to left, that's all! No way to do this as a prefix (unless we somehow found a top down that has that dependency order, but I do not think there is one for this problem). With this in hand, for a given cell, we pick our next stopping point and recurse. The same turn-less rules apply. Note we return dp[1] NOT dp[0] at the end. As dp[x] means we consider picking from x..., it does NOT mean we are solving for the x... problem. This is because of the edge case dp[0] letting us pick up a single stone which is not allowed by the problem. 5/ Now for the grand finale, O(n) bottom up turn-less dp Similar to 4, but we somehow need to store all the suffix data. We can't rebuild a suffix dp each time or that is n^2, or loop through every individual option (as that is just solution 4). Instead, we do dp[i] = max(pf[i] - (dp[i + 1]), dp[i + 1]) We either take the sum of all of these stones and lose the next persons score, or try a future dp which is better! It seems like a clever way to compress the suffix dp concept directly into the dp, sort of. Also note the base case for dp[n-1] at the last stone, is just the sum of all stones.
Drill Type:
Mindsolvere-read notes carefully, takeaway from all problems, main ones include: -turn vs turnless, when can we do turnless and why? -cached loop should not have a fake escape hatch -dp[x] actual meaning is for selecting between x..., nice way to formulate this -when we remove the turn we are just maximizing our score - their score -maximizer vs minimizer methods are different when we have a turn, otherwise we always maximize
Solutions:
3114. Latest Time You Can Obtain After Replacing Characters
Problem Summary:
We have a time like 1?:?3 find the latest 12-hour time we can make (00:00-11:59) Can do casework, watching the edge case so we don't produce 12:00, or just loop through all options
Solutions:
2075. Decode the Slanted Ciphertext
Problem Summary:
We have a string of text and we basically need to read the characters in some weird diagonal fashion, do so
Notes:
Just measure the width, start at the top, and jump by the right width
Solutions:
716. Max Stack
Problem Summary:
Design a stack that supports push, pop, peek top, peek max, pop max. Note if there are multiple maxes, we pop the top most one. Top should be O(1) and all other logN.
Notes:
Note: To dedupe duplicates we store IDs AS WELL which allows things like popping the max and if duplicates, popping the topmost one I think a SortedList literally supports all of these. Just be mindful to insert (-number, -idx) or something to handle popping the topmost largest. I was also able to use a lazy max heap and a stack. With some adjustments we can make more calls true O(1) but the other calls become amortized (worst case N). There's some DLL + sorted container thing but I think it's not actually optimizing anything
Drill Type:
Mindsolvereview notes make sure I know the basic heap method to implement, maybe look at code
Solutions:
1982. Find Array Given Subset Sums
Problem Summary:
We have N <= 15 numbers in an array, <= 1e4 and >= -1e4. We don't know the numbers, but we have all 2^n subset sums. Find the original array.
Notes:
First observe the minimum sum is going to include all negatives and no positives. We can find the frequency of that min sum to determine the number of 0s. Now we want to find the frequency of 1s, we can analyze the frequency of "min+1" as that would just be all negatives + an extra 1. We need to do a bit of careful math here to account for 0s. But WAIT, this isn't telling us how many 1s there are, because this number could tell us how many -1s there are too, that simply got removed from the negative array. So it is signless. Now compute the same for signless 2s. It's going to be all min+2 sums. However it's possible to form some of these with min+1+1. So we actually maintain a dp[x] which tells us the # of ways to construct x. We would subtract this count too. It looks like triple nested dp but it should amortize. Now we have the signless numbers. We need to get signed variants. We iterate over all 2^15 bitmasks of sign options. The moment we get anything where the minimum in our chosen mask equals the minimum in the input array, we have a valid answer. Imagine we have these values [1, 2, -3] so our min sum is -3. We can transition this min sum by any individual value in the array. If it were negative we exclude it from the min sum, so like -3 -> 0. If it's positive we add it. Same with a starting configuration of [-1, -2, 3]. So all transitions are the same and therefore all subset sums are the same. Also note if we iterate over all 1e4 sign-less numbers and dupe the DP, it's basically 1e4 * 2^n due to all these duplicates, but we can actually skip most of the number loops when we discover there are 0 copies of that, so we can reduce it to 1e4 * n
Drill Type:
Mindsolvere-read notes and code, on the nested dp transition idea, and also this clever subset sum stuff, how any subset that attains the right minimum sum, produces all subset sums listed - any of those options are identical
Solutions:
923. 3Sum With Multiplicity
Problem Summary:
Given N <= 3000 numbers <= 100, find the number of triplets (i, j, k) i < j < k where nums[i] + nums[j] = nums[k]
Notes:
1/ Super naive, enumerate pairs of indices, maintain a hashmap suffix for target value, O(n^2) 2/ Realized the universe domain is small, maintain a singleLeft and doubleLeft counter, treat our loop variable as the right element, O(n * U). Note that we explicitly treat the loop variable as the right edge, I had a brain blip where I ended up counting multiple triplets. 3/ O(n + U^2), just do two loops on the universe and a third lookup with some basic math
Drill Type:
Mindsolvere-read notes / code for #2, specifically how we use the loop variable as the right edge, instead of looping over all doubleLeft values and having a suffixRight counter too, that double counts triplets
Solutions:
1825. Finding MK Average
Problem Summary:
We have a stream of numbers, at any point if we have >= M numbers, we want to take the last M, exclude the smallest and largest K, and find the average of the middle
Notes:
First use a deque just to track the Mth number we lose out the left edge. Now this is like 2 rebalanced windows but we use 3. The implementation of this is key. The invariant I used in 2-rebalanced windows was "always insert in the right window, then rebalance only sizes". This also works here. But note that inserting in the right window was tricky. I tried toing left, then middle, then right window but actually there were edge cases I missed. The best way to do it is to check "must it go in here, then place here" and repeat for every window. So left window, then right window, then middle window, ended up being the clean order. To rebalance, we handle both underflow and overflow.
Drill Type:
Implementpractice the rebalanced windows idea
Solutions:
2479. Maximum XOR of Two Non-Overlapping Subtrees
Problem Summary:
Given a tree of N <= 5e4 nodes with values <= 1e9, find the maximum XOR of two non-overlapping subtree sums.
Notes:
We use small-to-large with a bit trie for O(n * B * log n) time. I wrote a full blog on these notes here: https://www.reddit.com/user/leetgoat_dot_io/comments/1sbcnwk/notes_on_small_to_large_merging_for_myself/ and here too: https://codeforces.com/blog/entry/152636 Also apparently we can avoid small to large by using a global trie I didnt' look into it. I think they query against sum(childTree) first then add the children to the trie, sort of thing precompute subtree sums S[v] global trie T (empty) ans = 0 def dfs(u): for each child c of u: ans = max(ans, query(T, S[c])) # query BEFORE recursing dfs(c) insert(T, S[c]) # insert AFTER recursing And also there is some euler tour thing
Drill Type:
Implementre-implement a true O(n * B * log n) solution, also re-read the blog
Solutions:
1902. Depth of BST Given Insertion Order
Problem Summary:
We are given a permutation of N <= 1e5 representing the order of node values we insert into a BST. What is the depth?
Notes:
If we could simulate the construction then we could just use that to find the depth. When we insert a node X it will either be the direct right child of the previously smaller element, or the direct left child of the next greater element. If we store node values in a SortedList we can find these easily. It gets inserted based on whichever is deeper. But we have a few things to prove: 1: Is it one of those two direct children? Well as we descend in the tree we start at (-inf, inf) as the boundary and tighten things. As we descend we update these boundaries. We will end up as the direct child of SOME node. It must be either our direct predecessor or direct successor in sorted order. Let's assume we ended up as the right child so we claim the parent is the predecessor. Call it A and our node C. Is there some node B that exists that is > A and < C? There cannot be, I think we can show we would have had to encounter it on our descent (think about it more). Similar idea for if we ended up as a left child. 2: We end up at the deeper one It seems unintuitive but the direct bigger and direct smaller nodes end up on the same root-to-something path actually, so one is below the other. And I think we need to keep descending until we clear both because that's how the (-inf, inf) bounds tightening process works. So we would end up at the deepest one. Some other ideas: -We could use an interval tree like [l, r] in a SortedList or something like this, and find our insertion point, I think, it's basically my idea just implemented differently. Vlad has a solution to look into if curious. -There is some stack idea which is O(n) by processing in value order not insertion order, did not investigate -We can process insertions in reverse, I saw two implementations one using DSU and one not, in solutions tab, did not investigate
Drill Type:
Mindsolvere-read notes, don't need to remember strictly but I guess just be aware of concepts like this
Solutions:
2046. Sort Linked List Already Sorted Using Absolute Values
Problem Summary:
We have a linked list of positive and negative values, sorted by absolute value. Make it sorted by normal value.
Notes:
I split into a positive and negative list, reversed one, then recombined, O(n) time O(1) space Also a one-pass trick where we loop and send negatives to the front or something
Solutions:
223. Rectangle Area
Problem Summary:
We have two rectangles. What is the total area they cover?
Notes:
It's total area of each one, minus their intersection. To compute intersection area we compute x intersection and y intersection and multiply. I did casework with a reusable function for the intersection of two line segments. We can be inside the other segment, contain the other segment, be fully to the left, be fully to the right, or one of two partial intersections. Note the partial intersection I had a small bug at first, here is the proper way to determine if we have this: (one is to the left of two, like this diagram) [----------] [-----------] # case 5, one is on the left of two w/ intersection if l1 <= l2: return r1 - l2 We compare left endpoints, not right ones
Solutions:
639. Decode Ways II
Problem Summary:
We have a string of numbers like 129812*313*12 We can decode it into letters like 111 can be (11, 1) which is k, a, or (1, 1, 1) which is a a a Also * can be replaced with any 1-9 Find the # of unique decodings
Notes:
Pretty basic casework, I think my code was clean I computed the # of ways as if dp(l) the l were a 1, a 2, and then I reused those in the star calculation Also can do state machine sort of, like # of sequences ending in 0, 1, available 2 (meaning the previous starting 2 was free), etc, alex wice has a solution
Solutions:
1156. Swap For Longest Repeated Character Substring
Problem Summary:
We have a string S of <= 2e4 letters, we can swap 2 characters, find the max size of consecutive letters
Notes:
Casework, either we fill a gap in two groups AAABAAAAAA or we just extend one group. I used dp(i) to see how far right we can go. Then added on a second dp after the gap. There are various sliding windows I'm guessing. Such as a 26N where we loop trying to make strings of that letter. Not sure about other window solutions.
Solutions:
534. Game Play Analysis III
Problem Summary:
We have a SQL table of games played on certain days by certain players, for each, find the # of games played up to that date by that player
Notes:
I basically did a subselect where for each row we do another nested O(n) scan counting all activities before that date, can improve to O(n) with parititon
Solutions:
176. Second Highest Salary
Problem Summary:
Find the 2nd highest distinct salary from a sql table
Notes:
Just select the max where its less than a subquery of the max
Solutions:
1103. Distribute Candies to People
Problem Summary:
We have N <= 1000 people and C <= 1e9 candies. We given 1, 2, 3, ... candies then loop around again N+1, N+2, ... until we run out. The last person gets whatever remaining amount. Find how many candies everyone gets.
Notes:
Obviously we can loop and simulate since we are bounded by rootC. But for a huge C I want to solve it. We do both. Find the # of full1 cycles formed with binary search or math. See code notes for math. Then do some basic n*(n+1)/2 stuff.
Drill Type:
Mindsolvere-read code notes, mainly to acknowledge quadratic formula vs binary search
Solutions:
2612. Minimum Reverse Operations
Problem Summary:
We have an array of N <= 1e5 0s and a single 1. We can reverse a subarray of size K. Some of the indices are given in a banned range (we cannot put the 1 there). Find the min # of swaps to reach every index, or -1 if not possible.
Notes:
Standard bfs is n*k. We don't want to do repeated work in a range l...r. To make this amortize nicely, track remaining positions in a sorted container. I used two for each parity (even length windows always swap parity, odd maintains it). O(n log n). I also did dsu nxt[i] which is a*n time but confusing. I think we can do a seg tree too.
Drill Type:
Implementre-code the sorted list version, particularly pay attention to the parity swapping logic and nice implementation of getting l...r in a sorted list
Solutions:
3888. Minimum Operations to Make All Grid Elements Equal
Problem Summary:
We have an MxN (M,N <= 1000) matrix of numbers <= 1e5 >= -1e5. We have K <= min(N, M). We can apply KxK range additions of 1 to every cell. Find the minimum # of operations to make all cells equal, or return -1 if not possible.
Notes:
This is the most evil problem on leetcode. Okay so first I tried to break it by doing range adds and range max queries in 2D but there's no poly log way to do this afaik. KD tree and sqrt decomp both take O(root(n*m)) time so I wasn't able to find a solution. But if we could get polylog we could try a 2 pass solution, not sure if it's actually valid. But first pass is set everything to the max of the full grid. Second pass is do it again. Handles cases like [[1,0,2],[1,0,2]] k=2 where the final answer is [[3,3,3],[3,3,3]] which is not the initial max of the grid. Alright now for the real solution. Call the smallest max we can attain T. Then loop over cells, we add some combination a*T + b to each cell. We do a 2d sweep line for both coefficients and constants. Say initially grid[0][0] is 5. Then we add T - 5 to this cell. Which is 1 coefficient and -5 constant. Repeat for all cells that are top left cells we add to. Now in a second pass finish looping over the cells that aren't valid top-left cells, like finish the sweep aggregation. Now at every cell we know the constant and coefficient we added. We wish to solve for T. We can't use one of the early cells because we forced all the first (n-k)*(m-k) top left cells to exactly equal T. So things would be tautologically true for all T (just see code for notes). So we use a different cell. But some of those cells give no info, so we actually need to try all of them until we can solve for T. Now we verify across cells that they all equal this T. But another edge case comes up where accidentally we allowed negative operations which isn't allowed. So we have to track min and max legal T in the first pass to gate it. There's some other observations to be found and I definitely did NOT extract max learning from this.
Drill Type:
Mindsolvehonestly just acknowledge this exists, I guess 2d sweep line and this concept of settings things to T even though we don't know what T is, are good learning
Solutions:
866. Prime Palindrome
Problem Summary:
We are given N <= 1e8, find the smallest prime palindrome >= N.
Notes:
A naive solution is to enumerate all first-halves, form palindromes, and check if they are prime. The check could use deterministic miller rabin which works. Also note to generate primes we could enumerate halves, doubling it to form even-lengthed palindromes. And we could insert middle digits to form the odd ones. Or, we could just take the half like 123 and do 12(3)21 basically merging it. The moment we find the smallest even and smallest odd length palindromes >= N we could terminate. However this would TLE since we won't find the even length palindrome! I had an else: break statement in my original code which actually made it work. More advanced thoughts, an even length palindrome cannot be prime, so we find the smallest odd length one. We could do the 12(3)21 trick to generate these and then terminate immediately. We could probably start our loop right around N too to skip numbers smaller than N. I bet we could probably do a rootN prime check instead of the fast logN and still finish in time. (I tested AI generated code for this and it worked fast!) Maybe some property about prime gaps shows we expect to find one soon. Also we could probably do more pruning, the number must end in 1 3 7 or 9 to be prime (except 2). Okay now let us discuss why even length palindromes are not prime, and we can skip them, besides 11. We wish to prove every even length palindrome is not prime, except for 11. LEMMA 1: First we want to show that (a*b) % c = ((a%c) * (b%c)) % c for instance (26*31) % 8 = ((26%8) * (31%8)) % 8 = (2 * 7) % 8 = 6 Observe that A is going to be some multiple of C, with some remainder. Like 26 is 3*8 + remainder 2. Same with B. A = (q1*c) + r1. B = (q2*c) + r2. A*B = q1*q2*c² + q1*r2*c + q2*r1*c + r1*r2 (just expand out with algebra) We wish to compute this big sum, modded by C, to get (A*B) % C. Clearly (q1*q2*c^2) % c = 0. Same with the second and third terms. Thus we are left with (r1 * r2) % c. Well r1 is exactly A % C, and r2 is exactly B % C. Substitute in these terms into the above equation. Thus we have completed the proof for lemma 1. --------- LEMMA 2: 10^k % 11 = (-1)^k % 11, for all k >= 0. For example: 10^3 % 11 = 1000 % 11 = 10. (-1)^3 % 11 = -1 % 11 = 10. (this is how negative mods work, by definition). Well we can write 10^k % 11 out like this. Let's say k=3. ((10 % 11) * (10 % 11) * (10 % 11)) % 11. This is done via lemma 1. Since -1 % 11 is exactly equal to 10 % 11, we substitute. ((-1 % 11) * (-1 % 11) * (-1 % 11)) % 11. We can actually collapse the above equation back down. Remember the original lemma 1: (a*b) % c = ((a%c) * (b%c)) % c Both sides of the equation are exactly equal, which means we can freely substitute either side. So we simplify back down to the collapsed state: (-1)^3 % 11. Remember we initially substituted k=3, so this is basically saying (-1)^3 % 11. Therefore we have proven: 10^k % 11 = (-1)^k % 11, for all k >= 0. ------- LEMMA 3 Any number with digits d1, d2, ..., dn, when modded by 11, equals d1*(-1)^(n-1) + d2*(-1)^(n-2) + ..., mod 11. Consider 526 % 11. We can say this is (5*(10^2)%11) + (2*(10^1)%11) + ... Well 10^2 % 11 is the same as (-1)^2 % 11 based on lemma 2. ------- Final proof: Take any even length palindrome. Say 123321. We want to show that when modded by 11, it is 0. This is (1*10^5 + 2*10^4 + 3*10^3 + ... ) % 11. Using the previous lemmas we can basically show this is like 1*(-1) + 2*(1) + 3*(-1) + 3*(1) + 2*(-1) + 1*1 = 0. Therefore every even length palindrome is divisible by 11. And since 11 is prime, it is the only even length palindrome that is prime.
Drill Type:
Mindsolvere-read notes crazy mod math proofs in here and stuff
Solutions:
1541. Minimum Insertions to Balance a Parentheses String
Problem Summary:
We have a bracket string except this time )) cancels out (. Find the minimum # of brackets to insert to make it balanced. Note that things must be even in order (not sure if this makes sense) but basically ( ()) must turn into ()) ()) as opposed to something like (()))) I think
Notes:
Stack but basically some extra work to account for left and right edges, Lee did an O(1) space that I think my stack could maybe reduce to? Not sure. Also some clever idea of substituting )) with ] but I didn't look into it.
Solutions:
3646. Next Special Palindrome Number
Problem Summary:
We have N <= 1e15. We want to find some palindrome > N, where every digit K in it, appears K times. Find the smallest such palindrome.
Notes:
First observe we can basically make palindromes of any length up to sum(1...10). So the answer is either going to be length N or N+1. Iterate over all masks of digit options. Prune those out that have >1 odd, or don't sum to the right possible lengths. Among that digit set we can generate palindromes by generating halves. It's not that many states. We can then just track the best so far. Some other notes: itertools.permutations takes n * n! time which is bad in cases like [4, 4, 4] it's going to generate that same permutation. If we do set(perms) then any downstream work only runs across the permutation once, which can actually still save time We could also implement a next_permutation function which takes O(1) amortized to skip over duplicate permutation generation entirely! I think we could also, given a bitmask, just backtrack dfs which might avoid duplicate permutations too. Guessing DFS before the bitmask would TLE since we do the validation "is this set of numbers correct" at the end, instead of the beginning like when we generate the valid mask up front Also we could precompute the entire set of valid palindromes here (this is tenable due to the extra digit K appears K times property) and then re-use across test cases
Drill Type:
Mindsolvere-read notes, good way to think about different angles of attack for problems like this
Solutions:
1024. Video Stitching
Problem Summary:
We have N <= 100 clips with (start, end) <= 100. We want to find the minimum of clips we need to fully cover 0...time (time <= 100) or return -1.
Notes:
Really annoying edge cases for two pointers. The high level is we sort clips by (l, -r). Start at a clip, walk right while in range, tracking the new right. Update result as we go. I had a lot of bugs. Also can obviously do other ideas like some sort of dp. DP is like dp[i] is min cost to cover 0...i. But this is n * universe time. Also claude had a clean nested while loop where the outer loop was while rightEdge < time My solution was O(n log n) due to sorting but we can convert this to jump game 2: Precompute maxReach[i] = farthest end among clips with start <= i. Then it's Jump Game II — at each position, you know the farthest you can go. This takes O(universe) time though clips = [[0,2],[4,6],[8,10],[1,9],[1,5],[5,9]], time = 10 position: 0 1 2 3 4 5 6 7 8 9 10 maxReach: [2, 9, 0, 0, 6, 9, 0, 0, 10, 0, 0] Now forget about clips entirely. You're at position 0 and can jump to any position up to maxReach[0] = 2. That's one jump. From anywhere in [0, 2], the farthest you can reach is maxReach[2] = 9. That's two jumps. From anywhere in [0, 9], the farthest is maxReach[9] = 10. Three jumps.
Drill Type:
Implementre-read notes, probably re-implement my way, jump game 2 idea seems kind of confusing
Solutions:
2029. Stone Game IX
Problem Summary:
We have N <= 1e5 stones of size <= 1e4. Alice and Bob take turns picking up stones. You lose if the removed stones sum to a number divisible by 3. Who loses?
Notes:
Note Alice cannot take a 3 at first so she must take a 1 or 2. After that, we always want to take a 3 because a 3 is a safe move for our opponent, so both players take all the 3s. Now it's basic casework / logic at the end since the sequence of moves is forced.
Solutions:
1914. Cyclically Rotating a Grid
Problem Summary:
We have an NxM (N,M <= 50) grid and we want to cyclically rotate each "layer" by k <= 1e9 steps, return the resulting array
Notes:
First note on a given layer we can reduce K to K % layer border size. An easy implementation might be dp(r, c, dirTup, stepsLeft) which is O(n*m*(n+m)). But if we want math based O(n*m) solutions the cleanest way is to iterate on layer number, for each later run 4 loops to gather cells, compute the shifted value, and rewrite
Drill Type:
Mindsolvesee code, so clean
Solutions:
3875. Construct Uniform Parity Array I
Problem Summary:
We have N distinct numbers and want to make a second array the same size where every number is odd or every number is even. For each index i, we set it to nums1[i] or it is nums1[i] - nums1[j] for some j != i, is this doable?
Notes:
We can test both odd and even, find out the answer reduces to return true lol
Solutions:
3876. Construct Uniform Parity Array II
Problem Summary:
We have N <= 1e5 distinct numbers <= 1e9. We want to make a second array of the same size where all numbers are either odd or even. For each index we must either set nums2[i] to be the original nums1[i] or it is nums1[i] - nums1[j] for some j!=i and nums1[i] - nums1[j] >= 1. Find if it is possible.
Notes:
We just maintain the smallest odd number in nums1 and check both options
Solutions:
3877. Minimum Removals to Achieve Target XOR
Problem Summary:
We have N <= 40 numbers N <= 1e4. Find the minimum number we can remove so the remaining XOR equals target.
Notes:
Well knapsack dp works I just didn't see it... So I did meet in the middle. Split into two groups of size 20. Generate all XOR options, I think there may be a faster way than 2^20 * 20, like doing xors = [1] and then doing xors = [x ^ y for y in xors] sort of thing. Also apparently xor basis can do bigger constraints
Drill Type:
Mindsolveremember mitm idea, and also I think I can generate the list of xor combos faster than n * 2^n by doing the like xors = [v] and then xors = [x ^ y for y in xors] sort of style, I think this logic is right
Solutions:
2573. Find the String with LCP
Problem Summary:
We have an lcp array of up to size 1000x1000. lcp[i][j] is the longest common prefix of some s for s[i...] and s[j...]. Construct the lexicographically smallest s that adheres to these, or show it is impossible.
Notes:
First if lcp[i][j] is non-zero then s[i] == s[j]. We can union these. We can just union these two for an n^2 loop, no need to do n^3 which would fail, by looping on the length of the prefix. Now go left to right, we want to use earlier letters `a` at the start, and fill out the group. We can use unionFind.find method to make this kind of easy to work with. We know this letter can only be used at those indices, like a at the start and anywhere else in the union group, or more indices would have been grouped via lcp[0][i] = at least 1. Construct this and then verify it works (can use dp to verify, dp(i, j) gives us the lcp of our string). Intuitively verifying makes sense the lcp's hold up.
Solutions:
3887. Incremental Even-Weighted Cycle Queries
Problem Summary:
We have N weighted edges of 0 or 1. We process edges in order. We add an edge if no cycles of odd weight sum get created, otherwise we skip. How many get added?
Notes:
I did this sort of weighted DSU thing. We measure distance to root. Remember DSU is a tree though not a graph. But still. If two nodes aren't connected we don't form any cycles anyway, so connect. If they are, we would form a new cycle. Check a->parent distance and b->parent distance and our new distance is those two + our new edge weight. If even it is guaranteed all cycles are even. Not airtight on this but I had intuition. Also could use XOR dsu instead of weight but it's same thing.
Drill Type:
Mindsolvejust remember that augmented dsu exists lol.
Solutions:
3886. Sum of Sortable Integers
Problem Summary:
We have N <= 1e5 numbers <= 1e5. K is considered sortable if it is a factor of N and we can used K-sized chunks that we cyclically rotate, and the resulting array is sorted. Find the sum of all K.
Notes:
We can factorize N with sqrt method or fast factorize. Now to test an N we look at each chunk. The min of a chunk must be >= the max from before. And each chunk must be sortable. We could check the chunk maxes with sparse tables or just iterate through every index anyway. To check the sortability it is sufficient to see if a chunk has at most one drop, including the wraparound point. So [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5] fails because 10->5 and 5->1 drop. Probably can be shown with necessary and sufficient conditions. We could even query this in O(1) per chunk. I ended up finding the smallest index in the chunk with the biggest index to the left, to catch cases like [1, 1, 5, 5, 1, 1] actually being sortable, but we must start at the 3rd 1. With these in hand, we could run #divisors scans over n. We can even do O(n) overall instead of d*n. For each chunk we compute # of descents in O(1) with prefix query, and we can find the next drop with a nextDrop[i] pointer. Now if we have 0 drops the min is chunk[0]. If we have a drop the min is near that drop position which we can find with nextDrop array. Now every divisor costs n/k which we sum over all k which I think is O(n) or something.
Drill Type:
Mindsolvereview notes for cyclic sortability
Solutions:
3885. Design Event Manager
Problem Summary:
Make a class where we have events (eventId, priority). We can update priorities and get the eventId of the highest priority, or if tied, the smallest eventId
Notes:
SortedList, lazy heap
Solutions:
3884. First Matching Character From Both Ends
Problem Summary:
Find the smallest index of a string where the opposite end is the same
Notes:
s[i] == s[~i] ;)
Solutions:
3883. Count Non Decreasing Arrays With Given Digit Sums
Problem Summary:
We have N <= 1000 and want to make an array that long. Every number <= 5000. Also for each index we are given a required digitSum, the sum of the digits for that number must match. And the final array must be mono-increasing. # of arrays we can make?
Notes:
Precompute digit sum -> list of options. Max is 365 options for a given sum. Naive dp is dp(i, prevNum) and loop on 365, this is n*5000*365. We can do bottom up prefix sum dp (probably top down too). dp = [0] * 5001 (# of ways to make a sequence end with that digit). Loop on N, loop on the new value, add all prefix possible ways. Now it is n*5000 + n*365. I think we could make it n*365 by making a sparse dp instead of the 5001 sized table, since the previous dp can only end in up to 365 options.
Solutions:
3882. Minimum XOR Path in a Grid
Problem Summary:
We have an MxN (MxN <= 1000) grid of numbers < 1024. Find the min path XOR going from top left to bottom right, moving down or right only.
Notes:
dp(r, c, xor) works.
Drill Type:
Implementpractice implementation to figure out when do we include the xor of the current value, in the dp call or before the dp call? both should work just think clearly
Solutions:
3881. Direction Assignments with Exactly K Visible People
Problem Summary:
We have N <= 1e5 people and we are standing at position pos. People are L or R (they choose). If they are L and on the left of pos, we can see them. If they are R and on the right, we can see them. How many arrangements can we see k people?
Notes:
Could see 0 on left K on right, 1 on left K-1 on right, etc. Loop through options and sum with combinatorics. Multiply by 2 at the end to account for ourself being 2 options. OR, ignore position entirely. We have N-1 other people. 1 if visible 0 if not. So it's a single nCk operation.
Solutions:
3880. Minimum Absolute Difference Between Two Values
Problem Summary:
Given N numbers that are 0 1 or 2, find the min distance between i and j so that nums[i] = 1 and nums[j] = 2
Notes:
Can one pass easily
Solutions:
C1. Equal Multisets (Easy Version)
Problem Summary:
We have an array of size N <= 2e5 with A[i] <= 2e5. We have K <= N. A is a permutation. We also have an array B with a mix of numbers from 1 to N, and -1s. We can make B cool if every window of size K is a permutation of that window in A, after substituting -1s. Is it cool?
Notes:
Let's look at the first window. When we drop out the left number, we must drop the same number. I think it is as simple as to update those dropped numbers (nothing for the rightmost ending window, we stop dropping things), and then check if we can make the last array a permutation / is every window a permutation. But my code wasn't this clean.
Solutions:
B. Mickey Mouse Constructive
Problem Summary:
We have X and Y <= 2e5. We want to construct an array with X 1's and Y -1's. Any time we can partition that array into groups of the same sum, that is a penalty. Across all arrays with that many X and Y, what is the min penalty? So two separate partitions for the same array give two penalties.
Notes:
Call the sum X-Y. Say it is 50. The sum changes by at most 1 each step left to right. This means we would necessarily have 25 groups of 2, 10 groups of 5, etc. So for every divisor we get a penalty. Intermediate value theorem. Note the edge case when the sum is 0 there are no divisors. We can reach this minimum with [1, 1, ..., 1, -1, -1, ..., -1] but I didn't observe that
Drill Type:
Mindsolvere-read, just mind blowing problem
Solutions:
A. Antimedian Deletion
Problem Summary:
We have a permutation of size N, we can choose a subarray of size 3 and delete either the smallest or largest number. For each index, find the minimum length of an obtainable array that contains that number after any amount of operations.
Notes:
Any number can survive in a group of 3 so it's just 2 for everything, unless the array is size 1
Solutions:
C1. A Simple GCD Problem (Easy Version)
Problem Summary:
We have N <= 2e5 numbers <= 1e9. We want to reduce numbers, but the GCD of any subarray must remain unchanged. How many can we reduce?
Notes:
If we preserve GCD pairs, then GCD of any subarray is preserved. Imagine (a, b, c) and we preserve the a<>b gcd with (a', b', c). Now the gcd of all 3 is going to be the same too. To reduce a neighbor we must preserve both adjacent pairs. We must be a multiple of either previous GCD, the smallest we could be is their LCM as both need to be factors. Check how many numbers have this LCM <= a[i].
Drill Type:
Mindsolvere-read notes, part about gcd staying the same is sufficient with just pairs
Solutions:
B. Simply Sitting on Chairs
Problem Summary:
We have N <= 2e5 permutation. We play this game: Now, you play a game. You visit each chair sequentially, starting from the 1 -st chair. At the 𝑖 -th chair, you can do the following: If the 𝑖 -th chair is already marked, then you end the game immediately without sitting on it. Otherwise, you can choose to sit on the chair or skip it and move to the next chair. If you choose to sit on the chair, then after standing up, you mark the 𝑝𝑖 -th chair and move to the next chair. What is the max # of chairs we can sit on?
Notes:
1/ If we pick a chair as the last chair we sit, then all preceding chairs > that number can be taken. I used fenwick tree for this. We can also take # of chairs with i <= a[i] which I used prefix sum query. O(n log n). 2/ There is some exchange argument which shows we should always sit in the last chair!
Solutions:
A. A Simple Sequence
Problem Summary:
We need to form a permutation of size N where a[0] % a[1] is >= a[1] % a[2], and so on
Notes:
[5, 4, 3, 2, 1] works :D
Solutions:
379. Design Phone Directory
Problem Summary:
We initialize a class that has up to 1e4 available numbers (from 0 to 1e4-1). We need to support: -Provide number (gives us a number that is available) -Check if number is used -Release used number
Notes:
Since we aren't looking for smallest we can literally just maintain a list of numbers, give the popped number, and also use a set to maintain what is available or not, now everything is O(1). We allocate memory up to maxNumber here, but we would do that even if we maintained REMOVED numbers instead, if the problem were designed such that a lot of calls to using a number could be made. Basically, whitelist vs blacklist might not make a memory difference depending on the constraints. --- Or we can do my typical logN everything option. Store a SortedList of used numbers, currently empty. When we want to get a number, we could get the smallest one, by binary searching on the SL for the largest number where we have used all of 0...X. Then provide X+1. This looks better because we don't allocate up front but I guess if we use a lot of numbers we would allocate anyway. But we can't MLE because that would imply we used maybe 1e9 numbers which would have TLEd first! --- Similar to 2336. Smallest Number in Infinite Set, but summarizing all ideas here: 1/ We have only up to 1e4 numbers needed, we want to pop the smallest not in use, and be able to release numbers back into the structure. We can store all the free numbers in a SortedList and just use that. ALSO, do the frontier technique where we track ones available, maintain a frontier variable (everything >= x is available) and when we add back it goes in a heap. 2/ We have up to 1e9 numbers, we want to pop the smallest not in use, and also release numbers back. (this is just the other problem) We could just allocate 1e5 numbers into the SortedList and pop / add as normal, trusting we don't ever need to pop a number bigger than this, because there is a limit of how many pop calls get made. 3/ We have up to 1e9 free numbers, we want to get pop any number, get the smallest not in use, and add numbers back. I think same thing, even popping arbitrary ones doesn't matter, we can pre-allocate free ones since we know we are limited by the # of pop calls. ALSO, I think we could just not allocate free ones up front, but store used ones? The memory constraint should be the same, and I think blacklist vs whitelist memory would always be the same, but the benefit is we only allocate what we remove, instead of allocating what we don't remove. To do this, we binary search for smallest not in use with a pbds but I think that is log^2 N remmeber I don't think find k-th is O(1) --- These sorts of thoughts should cover all the ideas, we can combine them too --- FAST SET Store all available numbers, get we can just use next(1) in log_64(U) and release also log_64(U) to insert, O(1) for check
Drill Type:
Mindsolvere-read notes, contrast with 2336. Smallest Number in Infinite Set
Solutions:
243. Shortest Word Distance
Problem Summary:
Given a string of words and two different words, find the min distance between them
Notes:
Just loop and check previous occurrence
Solutions:
231. Power of Two
Problem Summary:
Determine if a number is a power of 2
Notes:
Check if the bit count is 1 and it is positive, also could use math
Solutions:
205. Isomorphic Strings
Problem Summary:
Determine if two strings are isomorphic, that is we can remap letters in s1 to new letters and now it equals s2
Notes:
Basically just walk along and maintain a map
Solutions:
155. Min Stack
Problem Summary:
Build a stack that also supports O(1) get min
Notes:
Just maintain a min stack
Solutions:
135. Candy
Problem Summary:
We have N <= 2e4 kids each with a rating <= 2e4. Each child gets at least one candy. Those with higher ratings than their neighbors must get more. Find the minimum # of candies to give.
Notes:
Go in order of low to high rating, for each rating, for each kid with that rating, analyze their neighbors, and bump if needed
Drill Type:
MindsolveSolutions:
136. Single Number
Problem Summary:
We have a list of numbers, everything appears twice except one. Find that one in O(n) time and O(1) space
Notes:
bitwise XOR
Solutions:
111. Minimum Depth of Binary Tree
Problem Summary:
Find the minimum depth of a binary tree, the min depth is the earliest position of a leaf node
Notes:
BFS is good, but if we use dfs I found it easiest to make our base case if we are a leaf node, NOT if we are null, and it was still a bit janky
Solutions:
110. Balanced Binary Tree
Problem Summary:
Given a binary tree, determine if it is height-balanced. Height balanced means the depth of both subtrees at most differs by 1
Notes:
We can find the max depth of each subtree in the dfs function, also use a global to determine if any fail
Drill Type:
Mindsolvequick re-read / look at code
Solutions:
128. Longest Consecutive Sequence
Problem Summary:
We have N <= 1e5 numbers each <= 1e9. Find the longest consecutive sequence [X, X+1, X+2, ...] in O(n) time.
Notes:
Each number could be the start of a chain. Check if it is the start (using a set). If if is, count up.
Drill Type:
Mindsolvequick review
Solutions:
935. Knight Dialer
Problem Summary:
We have a knight standing a phone pad. It can only stand on numbers not # or *. Find how many phone numbers of length N <= 5000 it can type.
Notes:
dp(number, movesLeft) works. We can also matrix expo! Track # of ways to end at each cell, for every number, then define the transition matrix and exponentiate.
Drill Type:
Mindsolvequick acknowledgement it can be done with matrix expo
Solutions:
2007. Find Original Array From Doubled Array
Problem Summary:
We have an array of length N <= 1e5. We then took every number, doubled it, added it to the array, and shuffled it. Find the original array, or return [] if not doable.
Notes:
Sort and go from high to low. If there is a frequency of the high number left, subtract it from the map and also half that number (make sure that number is even, otherwise we fail immediately, like if the biggest number is 7 that can't have been a doubled number).
Solutions:
2122. Recover the Original Array
Problem Summary:
We original had an array of size N <= 1000. We then picked some positive integer K and formed two arrays, one is every number + k, the other is every number - k. Those two arrays got mixed up into one array. What was the original array?
Notes:
We can test all possible Ks. Take the biggest number, compare it to every other number, the difference is `diff`. A possible k is `diff / 2`. There are N of these possibilities. For each one we run a testing alg. Start high to low numbers, if no frequency for that number left, continue. Otherwise subtract from that number and that number - 2 * k. O(n^2) in total.
Drill Type:
Mindsolvejust quick re-read
Solutions:
1238. Circular Permutation in Binary Representation
Problem Summary:
Generate a grey code of size < 2^16 where the first number is `start`
Notes:
Just generate a grey code then rotate it, can use backtracking or the linear grey code
Solutions:
294. Flip Game II
Problem Summary:
We have a string of N <= 60 with + and - signs. On a turn we flip two adjacent ++ to become --. We lose if we cannot make a turn. Who wins? Also max + streak in the initial string is size 20.
Notes:
We can use backtracking (just mutate a list that is the state of the string) or dp(tuple) where the tuple is a sorted tuple of sizes. Didn't think about complexity.
Drill Type:
Mindsolverefresh idea to use dp here even when it is not obvious
Solutions:
2489. Number of Substrings With Fixed Ratio
Problem Summary:
We have a binary string and have two numbers num1 and num2 which are coprime. We want to select substrings such that the ratio of 0s to 1s is num1 : num2. Find how many substrings can do this. N <= 1e5.
Notes:
When we encounter a 0 we gain num2 and when we encounter a 1 we lose num1. Now we can use lop off method. Also note the numbers didn't need to be coprime for this. Votrubac had some weird dp solution but not sure if complexity is actually good: https://leetcode.com/problems/number-of-substrings-with-fixed-ratio/solutions/2864607/dp-math-by-votrubac-egr0/
Drill Type:
Mindsolvere-read notes
Solutions:
306. Additive Number
Problem Summary:
We have a string of numbers of length N <= 35, we want to split it into adjacent numbers such that every number is the sum of the previous two (except the first two). Can this be done?
Notes:
dp(i, prevNum, prevPrevNum) works, a lot of thoughts around showing this complexity is actually really fast because there are so few states, even without caching it works
Solutions:
3489. Zero Array Transformation IV
Problem Summary:
We have N <= 10 numbers with values <= 1000. And Q <= 1000 queries [l, r, val] where in that query, we can choose some subset of indices from l...r, and subtract exactly val. We wish to make the entire array all exactly 0s. What is the minimum # of queries we need to process (in order) to zero-out the array, or -1 if not doable.
Notes:
Solve each number separately, now we get standard knapsack dp. Note that we can reframe this dp a bit to make it map to booleans, thus we can speed up with a bitset.
Drill Type:
Mindsolvereview code, understanding of two ways of framing the top down dp (return early index, or could return a boolean), reminder about bitset
Solutions:
3700. Number of ZigZag Arrays II
Problem Summary:
A zigzag array uses only numbers l...r (l,r<=75), no two adjacent are the same, no three consecutive are strictly increasing or decreasing. How many sequences can we make of length N <= 1e9?
Notes:
Imagine we have the # of sequences ending in all l...r where the next number needs to be higher, or lower. So our state is 2 * (r - l + 1). We can define a transition matrix. Think in terms of the final state vector. The answer to a row in that final vertical vector is like coefficient_1 * prevstate_1 + coeff_2 * prevstate_2 etc. So do a bit of logic to fill out the transition matrix. Also seed the initial vector with all 1s (we put any starting number, next option goes both down and up). Then matpow with n-1 transitions (we already applied 1 transition in our base case). Then multiply the input vector by the raised matrix. apparently can be done in m^2 log n with Berlekamp–Massey: https://codeforces.com/blog/entry/61306
Drill Type:
Implementre-implement and remember ways to think about the matrix multiplication, do transition matrix * old vector = new vector
Solutions:
1515. Best Position for a Service Centre
Problem Summary:
We have N (X,Y) points with N <= 50, X,Y <= 100. Find the minimum distance to all other points (euclid distance, not manhattan), with up to 1e-5 error.
Notes:
First imagine we have a normal convex function like y=x^2. It has one global minimum. If we sum N different convex functions it also has one global minimum. We could find this via ternary search, measure two points m1 and m2 and if m1 <= m2, our answer must exist on the left of m2. Now imagine we have "bowls" or "cones" so like 2d convex functions. Similarly the sum of multiple of these is a final bowl with a global minimum. We can find this with nested ternary search. We fix an X. Among that "slice" is a normal curve like y=x^2, so we ternary search for the best Y. Now we can get the cost of (x, y) by checking the euclid distances. We want to find the best X, so we ALSO ternary search among these slices. I think we could use the m and m+1 version of ternary search (two adjacent points, so like binary search) if we pick a delta that is < our epsilon, or something like this, now we reduce the search space by half? some other ideas: keep sampling and zooming in (not sure if there is a proof): https://leetcode.com/problems/best-position-for-a-service-centre/solutions/731577/c-with-picture-zoom-in-by-votrubac-z55y/ some sort of greedy descent (claude said this is not actually simulated annealing): https://leetcode.com/problems/best-position-for-a-service-centre/solutions/731606/c-simulated-annealing-by-lzl124631x-4acg/ gradient descent: https://leetcode.com/problems/best-position-for-a-service-centre/solutions/731547/python-gradient-descent-with-armijo-step-4ldy/ weiszfeld alg: https://leetcode.com/problems/best-position-for-a-service-centre/solutions/6725744/c-solution-weiszfelds-algo-tc-on-sc-1-by-g962/
Drill Type:
Implementresolve from scratch! noting the cool double ternary search, the way we binary search on a continuous range, and using ternary search with thirds instead of two adjacent points and measuring slow (I think that's hard to do on continuous functions)
Solutions:
1908. Game of Nim
Problem Summary:
We have N <= 7 piles of stones each <= 7. Two players take turns removing any amount from any pile. We lose if we cannot remove an amount. Who wins?
Notes:
dp(tuple) works. However we can do way bigger constraints, see cses nim game I for the bitwise XOR solution
Solutions:
1053. Previous Permutation With One Swap
Problem Summary:
We have N <= 1e4 numbers all numbers are <= 1e4. In one swap find the lexicographically largest permutation that is smaller than the initial array.
Notes:
We swap two numbers. The number on the left must drop (so we are smaller). We want to drop the rightmost one possible. For it to drop, it needs to have a smaller number on the right. Loop backwards tracking smaller numbers. The moment we have a suffix smaller than us, we can swap. We want to swap with the leftmost occurrence to make it bigger still.
Solutions:
2336. Smallest Number in Infinite Set
Problem Summary:
We have an infinite set of numbers 1, 2, ... N. We want to find the smallest number in the set and also be able to pop and add numbers.
Notes:
Advanced method 1: Since N is small we can do linear stuff but there is logN for all operations. Maintain a PBDS that can find kth in O(logN) (I think O(1) not possible?). Now track missing numbers (initially empty). To find smallest in the set we will binary search for the largest N such that we have removed all 1...N, meaning the answer is N+1. Do so. It's log^2 N to popsmallest. Method 2: Realized I think I misread and we are supporting only pop SMALLEST, this is easier then We have frontier = 1 which indicates everything >= 1 is present And we have a SortedList of numbers that were re-added, < frontier. So if we pop pop pop now frontier=4. Then we add back 2. SortedList = (2). Now if we pop smallest we first check the sorted list. Like that. Similar to 379. Design Phone Directory, going to summarize all ideas there FAST SET IDEA: We hold present numbers 1 to 1000 (because N is small), pop smallest is just next(1) and then erase it, add back is insert
Drill Type:
Implementimplement in C++, re-read notes
Solutions:
2681. Power of Heroes
Problem Summary:
We have N <= 1e5 numbers with values <= 1e9. The power of a group is max(group)^2 * min(group).
Notes:
# for a given value A that is the max, it is like this # A*B*2^width + A*C*2^width + ... # which is A * (B*2^width + C*2^width + ...) # so I think we can track this rolling prefix value and update it, multiply the prior value by 2 # then add the new one
Drill Type:
Mindsolveread the code / notes
Solutions:
3879. Maximum Distinct Path Sum in a Binary Tree
Problem Summary:
We have a tree of N <= 1000 nodes with -1000 <= node values <= 1000. Find the max sum of a simple path where all values are distinct.
Notes:
Three ways: 1/ O(n^2 log n * n / W) For each pair of nodes, binary lift and get the bitwise OR of the entire path. If the # of bits is equal to the # of nodes, it works. 2/ O(n^2 * n / W) Run a dfs. The DFS returns chains of (chainSum, chainBitset). We aggregate pairs. Looks n^3 but it is n^2 since every pair of nodes gets considered once. 3/ O(n^2) Run a dfs on every node, which explores all other nodes. Used set to track values, seen set to not loop back on nodes.
Drill Type:
Mindsolvere-read all notes
129. Sum Root to Leaf Numbers
Problem Summary:
We have a binary tree with single digit numbers, a root to leaf path is like 123 if the elements are 1 2 3. Find the sum of all root to leaf paths.
Notes:
Learning a bit about math / how to shift numbers
Solutions:
118. Pascal's Triangle
Problem Summary:
Given numRows <= 30, generate the first numRows of pascal's triangle
Notes:
basically a form of dp
Solutions:
125. Valid Palindrome
Problem Summary:
Given a sentence, do a bit of string modification then check if it is a palindrome
Notes:
Just do the instructions then two pointers
Solutions:
115. Distinct Subsequences
Problem Summary:
Given strings s and t lengths <= 1000, find the # of distinct subsequences of s which equal t
Notes:
Just dp(i, j)
Solutions:
113. Path Sum II
Problem Summary:
Given a binary tree of numbers and a target sum, return a list of lists of root-to-leaf paths that sum to target
Notes:
dfs and if we hit a leaf update result
Solutions:
112. Path Sum
Problem Summary:
We have a binary tree of numbers, does any root to leaf path add to target sum
Solutions:
479. Largest Palindrome Product
Problem Summary:
We have N <= 8, find the largest palindromic integer that is the product of two N digit numbers.
Notes:
There are two ways to think about this: 1/ Go from palindrome -> factors We could generate palindromes from high to low. To do this, we can actually just generate first halves from high to low and mirror those. This is equivalent. Also we always get a palindrome of size 2N, despite the products ranging in length from 2N-1 to 2N (like 10x10 is 3 digits, but 99x99 is 4 digits). So we only need to check this one length. There's some more info on math throughout these solutions here: https://leetcode.com/problems/largest-palindrome-product/solutions/96306/java-solutions-with-two-different-approa-dg7c/ For a given palindrome how do we check if its a product of two factors? Well we could just enumerate the factors. But that might be too slow we need pruning. So we iterate on one factor going high to low. This means the second factor goes low to high. The moment the second factor is bigger than N digits we must break. Now we check if these two multiply and get our answer. Again more info on all the proofs in that post. 2/ Go from factors -> palindrome We want to start at high factors like (999, 999). Note that our answer is always going to be 9...9 again there is some proof of that. So our factors should only end in 1 3 7 or 9. Even endings and 0 and 5 cannot work. So I put (999*999, 999, 999) in a heap, popped it, check if product is a palindrome, if it is not we decrement both options and add back two things to the heap. Decrement from 999 -> 997 though skip 998. This barely passed in time. There was a 10x faster solution where we seed the heap with a bunch of values and decrement them all by 10 to keep the last digit the same. It worked faster.
Drill Type:
Mindsolvere-read notes, some lessons: -enumerate palindromes from high to low is same as enumerate first half high to low -heap idea in general is nice to enumerate products high to low -N*N is 2N-1 to 2N digits long
Solutions:
93. Restore IP Addresses
Problem Summary:
We have a string of up to 20 numbers like 25525511135 and want to make it into an IP address like 255.255.11.135 An IP address must have 4 numbers, all <= 255, no leading 0s (except for '0') Find all valid IPs
Notes:
We can use multiple for loops or backtracking
Solutions:
1801. Number of Orders in the Backlog
Problem Summary:
We have people making buy and sell orders. Each order has the price they want to buy or sell at, and the amount of units. As orders are made, if a buy and sell can be paired up (cheapest sell, most expensive buy), do so. How many unfulfilled orders remain in the backlog after all orders? All big constraints
Notes:
Since we cannot operate on individual orders we just batch them like (price, amount). I used two heaps. Min heap for sell and max heap for buy. We pop from heaps repeatedly as needed. No need to merge elements in a heap based on if the price is the same, we can just re-insert that into the heaps.
Solutions:
418. Sentence Screen Fitting
Problem Summary:
We have a sentence of words. We must type them with spaces like "hello my name is ishaan". We have a screen of size rows * cols and each letter takes up a col. We can't split up a word across multiple letters. How many full times can we repeat the sentence?
Notes:
1/ Pure brute force, track our current row and col. Note the nice implementation of always adding a space after the word even if it clips off the row. This is O(rows * cols) which TLEs. 2/ For each word, imagine it was the starting point of a word. We want to type as much as possible. What word do we end on in this row? How many full sentences did we type? We can manually brute force compute these for every word. Its basically words*cols to compute. Once we have that, for each row, just bookkeep these variables. So it is O(words * cols) + O(rows) time. 3/ Do the above, but don't walk over each row and update, just use jump tables. We have to travel say 1101001 rows in binary, so with our jump tables maintain our score gain and next word index. O(words * cols) + O(log rows * sentences) time 4/ For each starting word, we could binary search how many words we can fit in, basically determining the next ending word and the score gain. Maybe easiest is to split into three parts. Binary search all the words at the end, like if our starting word is in the middle of the sentence array, see if we can reach the end. Then use basic math to compute # of full cycles. Then one more binary search for a prefix. Could optimize the above solutions with this. 5/ Notice that we operate in cycles. Say we start at word i=0, end at word j=5 (maybe with two full sentences gained), for a single row. That ending word can differ at most N times where N is the # of words. Once we find that, we can use math to compute the # of full cycles. And a bit of other work for the prefix/suffix manually. 6/ Create a single string of all the words in sentence, maintain a pointer at characters (not wordIndex, but colIndex), for each row advance the col pointer by the width of the screen, using % to not overflow indexing, back up if we hit the middle of a word, basically like this: s = " ".join(sentence) + " " L = len(s) ptr = 0 for _ in range(rows): ptr += cols if s[ptr % L] == " ": ptr += 1 # space at boundary, skip it else: while ptr > 0 and s[(ptr - 1) % L] != " ": ptr -= 1 # back up to start of word return ptr // L
Drill Type:
Mindsolvere-read notes carefully lots of good ideas, see code
Solutions:
1155. Number of Dice Rolls With Target Sum
Problem Summary:
We have to roll a dice of K <= 30 sides. We roll it N <= 30 times. How many ways can we reach a sum T <= 1000?
Notes:
1/ Naive dp(i, currSum) for roll in range .... This is N*K*T time and N*T space 2/ Bottom up dp and ndp system, we iterate over N rolls, for each roll we iterate over the new roll sizes, and the previous states, this is N*K*T time and T space 3/ Bottom up prefix DP, since we are just adding ranges. This is N*K and T space 3.5/ We can also do sliding window dp instead of prefix basically the same thing just a bit easier: def numRollsToTarget(self, n, k, target): MOD = 10**9 + 7 dp = [0] * (target + 1) dp[0] = 1 for _ in range(n): ndp = [0] * (target + 1) windowSum = 0 for t in range(1, target + 1): windowSum += dp[t - 1] if t - k - 1 >= 0: windowSum -= dp[t - k - 1] ndp[t] = windowSum % MOD dp = ndp return dp[target] 4/ We can use matrix exponentiation where our state vector is size T (because we depend on all previous # of ways to reach every sum, to transition). But the transition matrix is T^2. To square it that takes t^3 time and we do that logN times (matrix exponentiation) which is t^3 * n which is too slow 5/ ntt is faster but not sure
Drill Type:
Implementreview all solutions and implement #3
Solutions:
500. Keyboard Row
Problem Summary:
We have a keyboard and a list of words, find all words that could be typed with only one row
Notes:
Honestly best way is a bitset and check submasks lol
Solutions:
503. Next Greater Element II
Problem Summary:
Given a circular array find the next greater element
Notes:
we can double the array and generate the answer, or just loop over the stack twice but don't push the second time, which is cool
Solutions:
498. Diagonal Traverse
Problem Summary:
Given a matrix, return a diagonal snake-like traversal of it
Notes:
I maintained our current r, c, and if we are going up or not
Drill Type:
Implementshould implement this
Solutions:
492. Construct the Rectangle
Problem Summary:
We have a required rectangular area, we want two dimensions Length and Width, with L >= W and the difference minimized, find these two
Notes:
Generate factors in trial division rootN, test it, can even do in O(1) space like two pointers basically, or use pollard rho, or a number series field (ginormous N cryptographic scale)
Drill Type:
Mindsolvequick review of two-pointer divisors and pollard rho remember that's faster to factorize
Solutions:
496. Next Greater Element I
Problem Summary:
We have two arrays that are permutations of each other, for a number in array 1, find it in array 2, and find the next greater element in array 2, do this for all numbers
Notes:
brute force (small constraints) or monostack + hashmap
Solutions:
495. Teemo Attacking
Problem Summary:
We attack an enemy and poison them for `duration` seconds, we have a list of times we attack, how many unique seconds are they poisoned?
Notes:
just track the current right edge, refresh if we re-attack, if it expires then add to result
Solutions:
494. Target Sum
Problem Summary:
We have an array of numbers and a target sum. We can insert - and + symbols in between numbers. How many ways can we form the target?
Notes:
-dp(i, currSum) works, we cannot bitset since we need counts -dp optimization, note this: We split numbers into two groups, (+) call it P, and (-) call it N P+N (where N is positive) = total sum And we want P-N = target sum So 2P = total sum + target sum P = 0.5 * (total sum + target sum) Now find how many subsets add to P, just take skip dp but our currSum can't be negative anymore! so we cut states in half. -meet in the middle works since array is small -something about ntt / generating functions MITM code: def findTargetSumWays(self, nums, target): mid = len(nums) // 2 def allSums(arr): res = [0] for x in arr: res = [s + x for s in res] + [s - x for s in res] return res left = allSums(nums[:mid]) right = Counter(allSums(nums[mid:])) return sum(right[target - s] for s in left)
Drill Type:
Mindsolvere-read notes
Solutions:
120. Triangle
Problem Summary:
Given a triangle, find the minimum path sum to reach the bottom from the peak, moving to only the two below us
Notes:
dp(r, c)
Solutions:
122. Best Time to Buy and Sell Stock II
Problem Summary:
We have stock prices and can buy or sell multiple times, max profit?
Notes:
Only buy the increases, or can use dp station machine
Solutions:
121. Best Time to Buy and Sell Stock
Problem Summary:
We have stock prices, we can choose one buy and one sell date, max profit?
Notes:
standard find max on right, so one loop
Solutions:
3493. Properties Graph
Problem Summary:
We have groups of numbers, two groups are connected if they share a number. Find how many connected components there are. Relatively small constraints.
Notes:
I would just model each group as a bitset, aggregate, and union find or dfs.
Solutions:
3496. Maximize Score After Pair Deletions
Problem Summary:
We have N <= 1e5 elements, we can remove 2 from front, 2 from back, or 1 from each side. We must do this while we have >2 elements. Score is all elements we removed. Max score?
Notes:
If odd sized array we can only leave 1 element, we can leave the smallest behind If even we must leave 2 behind that are adjacent, find that
Solutions:
3495. Minimum Operations to Make Array Elements Zero
Problem Summary:
We have Q <= 1e5 queries [L, R] with R <= 1e9. For each query it represents all numbers L...R In an operation we can pick two numbers and floor divide them by 4. Minimum # of operations to make every element 0, across all queries?
Notes:
We cannot enumerate each L...R so instead we enumerate on required operations for a number type, like: # 1, 2, 3 -> 1 operation needed # 4, 5, 6, 7, ... 15 -> 2 operations needed # 16, ... 63 -> 3 operations needed For each bucket find how many numbers in L...R are needed. And get the total # of operations (the amount of numbers * operations to reduce that bucket type) Answer is ceil(ops / 2) since we can always pair up things. Not worried about a single standalone [L, L] which we cannot divvy up work in half, since as per problem constraints L<R, and we can always just pair up consecutive things basically
Drill Type:
Mindsolvequick re-read
Solutions:
3502. Minimum Cost to Reach Every Position
Problem Summary:
We are at the back of line, we can swap with someone in front of us for a cost, or move backwards for free, min cost to reach each position?
Notes:
It's basically a prefix minimum you only ever swap forward once
Solutions:
3498. Reverse Degree of a String
Problem Summary:
Given a string compute some new value following these weird instructions
Notes:
Just do the basic string work / math required
Solutions:
1886. Determine Whether Matrix Can Be Obtained By Rotation
Problem Summary:
Check if a binary matrix can equal another one after any amount of 90 degree rotations
Notes:
1/ transpose then reverse to rotate Transpose = make rows become columns Then reverse every row To rotate left we could also do: Transpose then reverse each column (instead of each row). Or equivalently, reverse each row then transpose. 2/ Do sets of 4 cycles like this, like center pieces on a 7x7 rubik's cube: def rot(): n = len(mat) for i in range(n // 2): for j in range(i, n - 1 - i): # save top-left tmp = mat[i][j] # bottom-left → top-left mat[i][j] = mat[n-1-j][i] # bottom-right → bottom-left mat[n-1-j][i] = mat[n-1-i][n-1-j] # top-right → bottom-right mat[n-1-i][n-1-j] = mat[j][n-1-i] # tmp → top-right mat[j][n-1-i] = tmp
Drill Type:
Implementimplement one of the two rotations at least
Solutions:
3035. Maximum Palindromes After Operations
Problem Summary:
We have a bunch of words, we can swap two letters between any set of two words (even the same word). Max # of palindromes we can make?
Notes:
We can process word sizes from small to large, we can also just count how many pairs we need for a palindrome say of size 5 or 10 or whatever. We don't need to track each letter type, rather just the total # of pairs. We don't even need to track single center letters because there will always be a letter that can go there.
Drill Type:
Mindsolvere-read notes / code, solution is very clean
Solutions:
721. Accounts Merge
Problem Summary:
We get a bunch of accounts which is a name followed by various emails. Some of the emails in two accounts are identical, meaning it's the same user. Return the merged accounts.
Notes:
Union find, get all emails, for each account union them together, now to reconstruct we can just find parents for every email and put that in a groups dict DFS is actually easy too. Looks like for each account we need to construct a bunch of edges first but in an account we can just make every edge connect to the first email, or every 2 adjacent edges connect Then we run dfs(node, bucket) with a global seen array
Drill Type:
Implementimplement union find: the easy reconstruction by just finding parent representatives for every node at the end, to reproduce the groups implement dfs: do that one too
Solutions:
2858. Minimum Edge Reversals So Every Node Is Reachable
Problem Summary:
We have a directed tree, we want to reverse edges so we can reach every other node, from some starting node. Find the min # of edges we would need to reverse, to make everything reachable, from every possible starting node. N <= 1e5
Notes:
Standard reroot dp, the transition is simple we only need to adjust for the one edge from parent->child In my dfs2 I just had dfs2(node) instead of dfs2(node, parent) and I reroot from node->child, maybe we can do it both ways? Update first drill: compute down[node] which is the first subtree in dfs2 we have up[node] which means all things above it, and any of their children To go from up[node] to up[child] in dfs2, do this: answer for child is up[node] Also down[node] But we remove down[child] And handle the single edge between node and child twice OR we can use full (entire tree) instead of up, to go from node to child It is full[node] (reaches everything) Subtract down[child] to dedupe Handle single edge CODE FOR USING UP: up = [0] * n res = [0] * n res[0] = down[0] def dfs2(node): for child in children[node]: # lets compute cost of up[child] upCost = up[node] # first go up from node... upCost += down[node] # now this is the cost to reach the entire tree, from node so far # but we want the cost to reach it from child # so if node->child cost 1 we don't pay that anymore if adj[node][child] == 1: upCost -= 1 else: upCost += 1 # now remove the down cost from child upCost -= down[child] res[child] = upCost + down[child] up[child] = upCost dfs2(child)
Drill Type:
Implementimplement the reroot dp, note any requirements for why we just have dfs2(node) here but maybe we need dfs2(node, parent) in others?
Solutions:
3469. Find Minimum Cost to Remove Array Elements
Problem Summary:
We have N <= 1000 elements and a[i] <= 1e6, in one operation we pick two of the first three elements and remove those 2, the cost is the max of those 2. If fewer than 3 elements remain, remove all the remaining ones. Return min cost to clear the array.
Notes:
dp(i, prevNumKept) is our state which is n^2 my implementation not the cleanest but I liked this question
Solutions:
3466. Maximum Coin Collection
Problem Summary:
Mario can drive between 2 lanes collecting coins or paying tolls, and can switch lanes (up to two times), max coins?
Notes:
Just dp(i, lane, moved)
Solutions:
3467. Transform Array by Parity
Problem Summary:
We have an array, do this: Replace every even with 0, every odd with 1, sort it
Notes:
Just bucket sort I bet we can even do in one-pass two pointers type of thing
Drill Type:
Implementhonestly I should code the two pointer read/write solution
Solutions:
3459. Length of Longest V-Shaped Diagonal Segment
Problem Summary:
We have a NxM (N,M <= 500) grid of 0s 1s and 2s. We can make some diagonal streak that goes 1, 2, 0, 2, 0, 2, ... it can also bend once into a V with a clockwise turn. Longest sequence we can make?
Notes:
Just dp(r, c, requiredValue, turnsMade, direction) which is n*m*3*2*4
Solutions:
3457. Eat Pizzas!
Problem Summary:
We have N <= 2e5 pizzas it is a multiple of 4. Every day we eat 5 with weights W <= X <= Y <= Z. On odd days we gain Z weight. On even days we gain Y weight. What is our max weight?
Notes:
We want all the biggest pizzas. For each odd day we gain gain the biggest ones. After that we basically take every 2nd biggest one. Also note we don't need a deque I just did it to make it easier. I kind of forgot my reasoning during contest but I guess I saw a proof why processing all odds first is optimal, this is what claude says: Oh wait, how is it that if we take all of the biggest for the odd days and then we take the second biggest a bunch of times for the even days, how can we prove that is better than like taking the biggest, then taking the s two biggest after that on an even day. So going odd even, odd even instead of like all odds, then all evens. How can we prove one is better?6:31 PMCompared greedy strategies by analyzing which elements each approach capturesCompared greedy strategies by analyzing which elements each approach capturesConcrete example. 4 days (2 odd, 2 even), top 6 sorted values: a ≥ b ≥ c ≥ d ≥ e ≥ f. All odds first, then evens: Odd picks: a, b (1 element consumed per pick) Even picks: skip c take d, skip e take f Total: a + b + d + f Interleaved (odd, even, odd, even): Odd: a Even: skip b, take c Odd: d Even: skip e, take f Total: a + c + d + f Difference: b vs c. Since b ≥ c, all-odds-first wins. The intuition: odd days consume 1 element from the top per pick. Even days consume 2 (skip one, take one). So odd days are "cheaper" — they extract value without waste. You want to let the cheap picks go first to grab the highest values, then let the wasteful even-day picks burn through whatever's left. Any interleaving lets an even day "waste" a higher-value element that an odd day could have grabbed for free.
Drill Type:
Mindsolvere-read notes
Solutions:
3456. Find Special Substring of Length K
Problem Summary:
Find if there is a substring of length K which is exactly one letter type, and the previous and next letters (if they exist) are different from the one in the k-window
Notes:
We could fixed sliding window with a counter or brute force
Solutions:
3450. Maximum Students on a Single Bench
Problem Summary:
Students are sitting on benches, find the max # of unique students on a bench
Notes:
Just store a set for each bench
Solutions:
3452. Sum of Good Numbers
Problem Summary:
Find the sum of numbers in an array which are greater than nums[i+k] and nums[i-k]
Notes:
Just enumerate and do it
Solutions:
3443. Maximum Manhattan Distance After K Changes
Problem Summary:
We start at the origin of a grid and have N <= 1e5 operations to move N S E or W. We cna change K of the operations with K <= N. What is the max distance from the origin we can achieve?
Notes:
E<>W and N<>S are handled separately. We can basically do casework trying to go as far in one diagonal direction as possible, at every step
Drill Type:
Mindsolvejust glance at notes / code (if notes didn't make sense)
Solutions:
3442. Maximum Difference Between Even and Odd Frequency I
Problem Summary:
Find the max difference in frequency of two letters in a string where one is odd and one is even
Notes:
find max/min freqs for odd and even
Solutions:
2330. Valid Palindrome IV
Problem Summary:
We have a string and can change any letter, can we make it a palindrome with exactly 1 or 2 differences
Notes:
count mismatched pairs
Solutions:
760. Find Anagram Mappings
Problem Summary:
We have two anagrams, we need to form a mapping of the indices
Notes:
just use hashmaps
Solutions:
774. Minimize Max Distance to Gas Station
Problem Summary:
We have N <= 2000 gas stations at positions <= 1e8. We can add k <= 1e6 new stations. Penalty is max distance between adjacent stations. Min penalty? Answers within 10^-6 accepted.
Notes:
Standard binary search just go until l + 10^-6 <= r This works because our res is always in the range l...r, think about it (look at code for this) Also a bit unclear about if we keep failing the check condition and doing l=m over and over and eventually we fail out of the loop, I feel like this could happen if the true answer is r (the max of stations) and we terminate before finding that, so maybe I need to make r = max(stations) + 1
Drill Type:
Mindsolvere-read notes / code
Solutions:
773. Sliding Puzzle
Problem Summary:
We have a 2x3 sliding puzzle, find min # of moves to solve it
Notes:
bfs, interesting form of bfs since the states are like a small grid
Solutions:
771. Jewels and Stones
Problem Summary:
Basically check all elements present in one string are in another, can use a bitset since its small not sure its faster
Solutions:
766. Toeplitz Matrix
Problem Summary:
Find if every major diagonal contains only the same elements
Solutions:
763. Partition Labels
Problem Summary:
We have N <= 500 letters and need to partition it in a way such that a letter type only appears in its partition, e.g. ababcc becomes [abab, cc], find this partition
Notes:
We keep going and update the rightmost letter index we have hit
Solutions:
2680. Maximum OR
Problem Summary:
We have N <= 1e5 numbers <= 1e9 and k <= 15 operations. We can double a number in an operation. Max bitwise OR of entire array?
Notes:
1/ We must apply all operations to a number with the max set bit. Proof, if we don't, we can never achieve 2^(msb + K). 2/ If we just test it for each number by doing that number left shifted by K OR the prefix OR, OR with the suffix OR, we find the solution Also just picking the max doesn't work e.g. [12, 9] k = 1
Drill Type:
Mindsolvequickly re-read
Solutions:
3432. Count Partitions with Even Sum Difference
Problem Summary:
Find the # of partitions where the prefix sum and suffix sum difference is even
Solutions:
790. Domino and Tromino Tiling
Problem Summary:
How many ways can we tile a 2xN grid with dominos and trominos
Notes:
Standard dp(i, isFilled) works or we can do matrix exponentiation didn't really look into that
Drill Type:
Implementimplement the matrix exponentiation version
Solutions:
791. Custom Sort String
Problem Summary:
We have a string defining a new alphabetical order and then a second string we need to sort based on the new order
Notes:
bucket sort, custom comparator
Solutions:
A. Flip Flops
Problem Summary:
We have N monsters with powers and we have a starting power C. We have K operations to increase a monster strength by C. When we beat a monster we gain its strength (we need >= strength to beat it). Max strength we can get?
Notes:
Process low to high and greedily use operations if we can
Solutions:
B. Array
Problem Summary:
We have N <= 5000 numbers and want to, for each index i, find the # of indices j>i where |𝑎_𝑖−𝑘|>|𝑎_𝑗−𝑘| for some k we pick. Find the max count of this for a given K independently for all numbers. ,
Notes:
We either are going to big a big K or a big negative K so can just brute force test in n^2 or use a seg tree in some way didn't look into it
Solutions:
C. Find the Zero
Problem Summary:
We have n <= 1e4. Our array is length 2*n (call this N). It contains all numbers from 1...n, and the rest are 0s. We can make up to n+1 queries on two numbers and it tells us if they are the same. We need to find a 0.
Notes:
We can do n queries on pairs worst case they are all like (X, 0) (Y, 0) etc Then we can do 2 more queries, X<>0 X<>Y, if both fail, we pick the not X Or if we did 0<>Y 0<>0 we win But this is n+2 queries Well actually we don't need to check one pair at all, it's a bit of casework: # DONT GUESS LAST PAIR # either # 1 0 2 0 3 4 | 5 0 6 0 (0 0) # 1 0 2 0 3 0 | 4 0 5 0 (6 0) # in case 1, we do 3<>0 3<>0, if both fail, we know the last pair is 0,0 # in case 2 we do 3<>6 3<>0 we nneed to guess one of the last two hmm # !!!!!!!! # or maybe # we do 3<>0 4<>0 in case 1, we guess the other 0 # we do 3<>6 0<>6, we guess the other 0 # we do 0<>6 0<>0 we win # !!!!!!!! # ^WORKING IDEA WICE LEARNING: Solve for a small n manually and go from there
Drill Type:
Mindsolvere-read notes about wice idea at the bottom
Solutions:
https://leetcode.com/problems/minimum-area-rectangle/
Problem Summary:
Given an array of N <= 500 points on a plane, find the minimum area rectangle that has 4 points on corners (doesn't need to contain all points)
Notes:
Enumerate n^2 pairs of points as the CORNERS I think we can also consider two points as the left edges or something didn't look into it not sure if faster than n^2 is doable
Drill Type:
Mindsolvere-read corner points idea
Solutions:
708. Insert into a Sorted Circular Linked List
Problem Summary:
We have a circular linked list that is mono-increasing, and a new value we need to insert, do so
Notes:
3 cases: -We fit between two nodes, put it there -We are bigger than the max or smaller than the min, put at that max->min point -All values are the same, we can put wherever
Solutions:
789. Escape The Ghosts
Problem Summary:
We have N <= 100 ghosts with coords (x, y) <= 1e4. We have a starting and ending location. Can we reach the end before any ghost intercepts us?
Notes:
BFS does not work since the grid is too big Note if a ghost can reach the target before us, they can intercept, otherwise they cannot. Proof if a ghost cannot reach the target before us, it cannot intercept us: Assume it can intercept us, that means it can reach the target at least at the same time as us. This means it could reach the target faster than its manhattan distance which does not make sense.
Drill Type:
Mindsolvere-read notes
Solutions:
383. Ransom Note
Problem Summary:
Tell if one string can be made from another
Solutions:
377. Combination Sum IV
Problem Summary:
We have N <= 200 numbers with values <= 1000 and need to form target <= 1000. How many unique sequences can we do this in? For example (1, 2, 2) and (2, 2, 1) both count if T=5.
Notes:
DP, but we cannot do dp(targetLeft, index) because we must allow duplicate orders, so put a loop inside the dp
Solutions:
374. Guess Number Higher or Lower
Problem Summary:
Standard binary search for guessing a number
Solutions:
373. Find K Pairs with Smallest Sums
Problem Summary:
Given two arrays of length N <= 1e5, find the K <= 1e4 smallest sum pairs
Notes:
In the sorted arrays, for each index i in nums1, store the index j in nums2 we are at. All these pairs to our array. When we pop we increment the j pointer. Use a heap.
Solutions:
370. Range Addition
Problem Summary:
Given an array of length N <= 1e5 we have U <= 1e4 updates which should add [l, r, increment] meaning all l...r gain by increment. Return the final array.
Notes:
Sweep line!
Solutions:
2157. Groups of Strings
Problem Summary:
We have N <= 2e4 words each of length at most 26 (each word all different letters). Two words are in the same group if they have the same letters, we can add a letter from one to reach another, delete a letter from one to reach another, or replace a letter from one to reach another. How many minimum # of groups are there and what is the largest size group?
Notes:
First any two words with the same bitmask are grouped together. For a given word, for each of its letters, consider that letter was gone. Then any two words sharing this missing one letter mask are grouped together. E.g. bat and cat, when we remove b and c, are 'at', and they should be grouped due to replacement Also any single deleted mask that is equal to another full mask, like dogs and dog, should be grouped do this with union find
Drill Type:
Mindsolvequick refresh on the remove a letter hashing technique
Solutions:
2712. Minimum Cost to Make All Characters Equal
Problem Summary:
Given a binary string of length N <= 1e5, we can invert some prefix or suffix with cost "length of prefix / suffix", min cost to make the entire string equal?
Notes:
Note we wouldn't invert a prefix of like 70% the length of the string since we could just invert the suffix of 30%, but doesn't change or solution We are not going to ever invert a prefix + suffix that overlap since the middle part is redundant So at some point is the dividing line, I had dp for prefix ...i to make it all 1s and 0s, same with suffix But we could also do a simpler observation which is basically flipping the mismatches (claude): Identified simpler greedy solution versus user's verbose DP approach Yeah, a bit. The key observation is: at each boundary where s[i] != s[i+1], you have to fix it. You either flip the prefix 0..i (cost i+1) or the suffix i+1..n-1 (cost n-i-1). These choices are independent, so just greedily pick the cheaper one: python def minimumCost(self, s: str) -> int: n = len(s) return sum(min(i + 1, n - i - 1) for i in range(n - 1) if s[i] != s[i + 1]) Your solution is correct, but you're tracking full prefix/suffix DP states when you don't need to — the decisions at each boundary don't interact with each other.
Solutions:
2591. Distribute Money to Maximum Children
Problem Summary:
We have M <= 200 money and C <= 30 children. We want to distribute money so every child gets at least $1, no child gets $4, and maximize the number of children with $8. How many is that?
Notes:
Could simulate but I did O(1) math: -If not enough money for everyone, we fail and return -1 -If every child can get at least 8 we return C -Now at least one child cannot, see how many 8s we have, if the last child is forced to take 4 and no other children to distribute that extra $3 with, then return eights - 1 -Otherwise return the number of eights we can make
Solutions:
3389. Minimum Operations to Make Character Frequencies Equal
Problem Summary:
We have a string of N <= 2e4 letters. In an operation, we can delete a letter, insert a letter, or change a letter to the next letter, like a->b. (z does not change to a). Find the # number of operations to make the frequency of all letters the same.
Notes:
Note that the answer frequency is not always one of the initial letter frequencies, for instance cccccbbbaa I think we make both a's b's Idea 1: if we try each letter frequency from 1 to N, to solve for that letter frequency, we are kind of doing work based on 26 not N, since we think in terms of letter counts Starting at letter 'a', we can either delete all of it or increase it up to the target, if it's too low, but if it is too high we could carry forward or delete If we think about carrying forward, and in a future state we have this excess, we could choose to "forget about it" and treat the previous carry forward more as a delete We don't want to track how many we carry forward in the dp state because it is too big, but also note we never need to carry forward by 2 or more, a->c is equivalent to -a +c. So simplest dp is dp(letterIndex, prevDeletedOrCarried) and we can use that previous carried amount (or pretend it was deleted) O(26n)
Drill Type:
Mindsolvere-read notes / code, particularly the part about how we represent the carried amount OR deleted amount in the same variable which makes the implementation easy
Solutions:
75. Sort Colors
Problem Summary:
Given an array of 3 colors, sort it
Notes:
Bucket sort, also some crazy one-pass algorithm specifically for 3 colors
Solutions:
3212. Count Submatrices With Equal Frequency of X and Y
Problem Summary:
Find the # of submatrices that contain the top left corner, and half an equal amount of Xs and Ys
Notes:
2D range prefix query essentially
Solutions:
3135. Equalize Strings by Adding or Removing Characters at Ends
Problem Summary:
We have a string initial length <= 1000, and a target <= 1000. In an operation we can add or remove a letter on the start or beginning of initial. Min # of operations to make it equal to the target?
Notes:
Thought: We loop on removing up to N from left and up to N from right. That means the remaining part must be a substring of target. Then we add on the remaining portions. Really we want the longest shared substring between them. Can do dp(i,j) to find the longest substring for i... and j..., must use those indicies, this is n*m. Can do rolling hash + binary search for n log n Can do suffix automaton or something for linear?
Solutions:
1300. Sum of Mutated Array Closest to Target
Problem Summary:
We have an array of N <= 1e4 numbers. If we pick some value X and change all numbers > X, to X, we want our sum to be as close to `target` as possible. Return the best X. If multiple with the same difference to target, return the smaller one.
Notes:
I binary searched on the answer. Find the smallest X such that our sum is still >= target. Then also test one below it. We could also sort, process elements from small to large. Test what if this small element was our X? There's some math to infer the exact middle point: https://leetcode.com/problems/sum-of-mutated-array-closest-to-target/solutions/463306/javacpython-just-sort-onlogn-by-lee215-nl7i/
Solutions:
3874. Valid Subarrays With Exactly One Peak
Problem Summary:
A peak is an index greater than its two neighbors. A valid subarray is one that contains one peak, and both L and R are <= K from that peak. Find the # of valid subarrays.
Notes:
Locate each peak, for each peak find its left and right peaks to understand our cutoff range. For a peak, we have left and right options based on K and our range. Use contribution technique.
Solutions:
B. Cyclists
Problem Summary:
We have N <= 5000 cards with values <= 5000. Each turn we take an element from the first K cards and play it, moving it to the back of the deck. Every card has a cost to play. We cannot exceed M total cost. There is a special win condition card at index p in the array. How many times can we play it?
Notes:
Naive n^2 passes. Look at the first K elements. If win con is there, play it. Otherwise play cheapest. Can optimize with heap to find cheapest in O(logN) for n log n total.
Solutions:
A. Bingo Candies
Problem Summary:
We have an NxN (N<=100) board with colored candies. Can we rearrange the board so no column or row has N candies of the same color?
Notes:
Idea is if a candy appears N-1 times in each row that's fine, we put a hole in every column. If more than that not doable.
Solutions:
C. Stamina and Tasks
Problem Summary:
We have N <= 1e5 tasks. Each task has a value c <= 100 and a difficulty p <= 100. We have stamina S = 1. We take tasks left to right. We can skip, nothing happens. Or we can take, score S * c_i, and S drops to S * (1- p_i/100) after. Max score up to six sig figs?
Notes:
Storing S in dp matrix dimension is untenable. But note if we look at task i and consider future tasks. We know the future best score for i+1... subproblem. If we take here we gain 1 * c_i but lose that multiplier on the future score. So we don't actually need S.
Solutions:
C. Even Positions
Problem Summary:
We have a regular bracket string of size N <= 2e5. But even indices were lost and replaced with _. The score of the RBS is we decompose it into pairs of brackets, and sum up the distances between pairs. For instance (()) scores 3 + 1 = 4. The inner () is score 1 since the distance is 1. Construct an RBS with minimum score.
Notes:
I had an intuition that we want to close previously open brackets as quickly as possible, saw some exchange idea but not well formed. To do this I will place a ) if we have at least 1 prior (, and we don't screw ourselves over in the future by overflowing with too many ). To prevent that second case, I took suffix sums to determine if it is safe. But claude says we don't even need this: Analyzed greedy bracket placement strategy versus tutorial approachThey didn't need the safe array. Their greedy is simpler: at each _ position, if the stack is empty, open. Otherwise, close. That's it. Your approach worries about "will closing here screw up the future?" The tutorial proves you never need to worry about that. Here's why: The _ positions are always at odd indices (1-indexed: 1, 3, 5, ...). The fixed characters are at even indices. The key observation from the tutorial: After processing an odd-length prefix, the balance is always exactly 1 After processing an even-length prefix, the balance is either 0 or 2 So whenever you're at a _ (odd index), the balance coming in is either 0 or 2. If it's 0, you must open. If it's 2, you close (greedily, to minimize cost). The balance never gets high enough that closing now could cause problems later, because the next character is always a fixed character that self-corrects. The proof that it never "screws you over": suppose you greedily close at some _ position but this leads to an invalid sequence later. That would mean the balance goes negative at some future point. But the balance after your close is 1 (was 2, now 1). The next character is fixed (even position). If it's ), balance becomes 0, and the next _ will be forced to open (stack empty). The balance oscillates between 0, 1, and 2 — it can never go negative. So your safe array was solving a problem that doesn't actually exist given the structure of the input (alternating _ and fixed characters). The greedy "close whenever you can" is always safe.
Solutions:
A. Strong Password
Problem Summary:
A passwords of letters takes 2 seconds for the first letter, 2 seconds for every letter different from the previous, and 1 second for every letter same as the previous, to type. We can add one letter. Return a new password with max time.
Notes:
If we can split two same letters like AA -> ABA, do it, basically
Solutions:
B. Make Three Regions
Problem Summary:
We have a 2xN grid of walls and empty space. We can place a single wall somewhere. Our initial grid has at most 1 region. How many cells could we place a wall in, to get 3 regions?
Notes:
Basically we need a formation like this: . O . # . # Where . is empty space, O is the cell we place, # were existing walls
Solutions:
D. Maximize the Root
Problem Summary:
We have a tree with N <= 2e5 nodes and values <= 1e9. In an operation we can increase a node's value by 1 and decrease all subtree nodes by 1. What is the max value we can make the root, such that no node goes < 0?
Notes:
My idea: We are bottlenecked by the minimum in our subtree. But that minimum can go up, based on its minimum. So postorder DFS. I did a nice trick where I put the results of postorder in an array, so I could loop over it twice, avoid DP / caching it. This is O(n) dfs. Could also binary search on answer, can we make the root X? We need to do this operations on the root X - rootVal times. Propagate that need downwards, adding over and over. At a leaf make sure our value is >= the summmed needs.
Drill Type:
Mindsolvere-read code my postorder dfs was nice here
Solutions:
E. Level Up
Problem Summary:
We have N <= 2e5 monsters with strengths <= N. We start at level 1 and battle monsters left to right. If the monster strength is < our level they run away. Otherwise we fight. We level up when we fight K monsters (flees don't count, we don't need to "beat" the monster also). K is not given its just arbitrary here. We have 2e5 offline queries (i, x), which is "do we fight the i-th monster if K=x"?
Notes:
If we process each K one at a time from 1 to N, we can basically do N + N/2 + N/3 + ... work which is N log N. At a given index in the array, say we start at i=0 for K=5. We want to know how far we have to go before we reach 5 monsters with strength >= our level (which starts at 1). We can find the Kth number GTE X in a range l...r in logN time online using a merge sort tree + fractional cascading. Since there are N log N of these points that's N log^2 N work total, which passes. Without fractional cascading is N log^3 N which supposedly works too. Also I think persistent segment tree can in some way do these queries but it can only find the value not the index or something? not really sure At first I tried some weird binary array segment tree idea which can find the Kth 1 in the entire array. For each K value from 1 to N we build a new segment tree and every monster is "on" (a 1-bit) at first. As we level up we turn off monsters. This works but I realized I was building N segment trees which is N^2... Then Claude suggested some more cursed method where we process all K simultaneously and can only use 1 segment tree but it felt too confusing. There is apparently some N log N solution, this is one example I didn't look into it: https://codeforces.com/blog/entry/132154?#comment-1177825 The type of fractional cascading I used here was a 2N memory version: Each node stores its sorted vector, but also a cntL array which is cntL[amt] is how many numbers from the first `amt` numbers in the SORTED array at these indices, are in the left child. So a standard MST query might be "# of elements >= X in a range l...r", we binary search at logN nodes and sum them up, log^2n query But now with the fractional cascading we do one binary search at the root node to find p, the # of elements < X. Say it's 10. Those are the 10 smallest elements. We can look at cntL[10] which is of the 10 smallest elements, how many are in the left child seg tree node? Say it's 3. We recurse to the left child and pass p=3. Now we know exactly 3 elements in this child are < X and we don't need to re-binary search. The walk is also a bit confusing, I think it's one of those seg tree walks you kind of have to think about how it takes logN time (conversation with Josh a long time ago), but basically our recursive walking function is hunting for the index in the global array, of the Kth elements >= X. If we hit a tree node and we have 1 element >= X, we found the index, send that back up. Otherwise we are going to be sending -1 back up in general as a sentinel. But we also need to send up the count of elements >= X. So in a node if we look left and are finding the 10th element, and the left had 7, we recurse right looking for the 3rd element >= X now.
Drill Type:
Implementimplement the merge sort tree with fractional cascading
Solutions:
1856. Maximum Subarray Min-Product
Problem Summary:
Given an array of numbers, a score is a subarray min * its sum. Find the max score.
Notes:
Consider each element as the min. See how far left / right it can go with two stacks. Multiply by that sum.
Drill Type:
Implementimplement monostack in both directions
Solutions:
2195. Append K Integers With Minimal Sum
Problem Summary:
We have N <= 1e5 numbers <= 1e8. Append K <= 1e8 smallest numbers, not in the array. Return the sum of those K.
Notes:
We cannot loop from 1 to max(array) and check if that number is in the array or not, even if after we hit the max we just do math, because the max could be big. Instead sort. Idk what my code was doing but I feel like I could just analyze every nums[i] - nums[i-1] pair and implement more easily
Solutions:
1224. Maximum Equal Frequency
Problem Summary:
We have N <= 1e5 elements <= 1e5. Count the longest possible prefix of nums where if we remove 1 element, every remaining element appears the same number of times
Notes:
Basically casework, see code, cases like a number appears once, a number appears many times, a number appears 1 more time than the second number, etc
Solutions:
1349. Maximum Students Taking Exam
Problem Summary:
We have an MxN (M,N <= 8) grid of seats, some seats are broken. Students can see left, right, left-up, and right-up. Find the max # of students who can take the exam with no cheating.
Notes:
Or state is dp(aboveMask, row) and we enumerate masks and check if they are valid. We can do a second isValid(topMask, bottomMask) to speed this up between different rows. Or maybe for a given mask precompute all valid next masks. But then we need to deal with broken seats. I did a canFitInRow dp also and even one more. I got O(height * 4^n) time complexity. apparently there is some hungarian algorithm + bipartate graph idea which is faster, bipartate in the sense that odd column students can never seen even column students: https://leetcode.com/problems/maximum-students-taking-exam/solutions/503790/python-hungarian-time-om2n2-space-omn-be-uhlp/ Why it's bipartite A student at (r, c) can see seats at positions: left (r, c-1), right (r, c+1), upper-left (r-1, c-1), upper-right (r-1, c+1), lower-left (r+1, c-1), lower-right (r+1, c+1). Notice every conflict is between adjacent columns. An even-column student only conflicts with odd-column students and vice versa. No two even-column students ever conflict, no two odd-column students ever conflict. That's the definition of a bipartite graph — two groups where edges only go between groups, never within. The key theorem König's theorem: In a bipartite graph, max independent set = total vertices - max matching. An independent set = a set of nodes with no edges between them = students who can't see each other = exactly what we want. So the problem reduces to finding the max matching. How Hungarian works For each unmatched node on the left side (even columns), try to find an augmenting path — a path that alternates between unmatched and matched edges, ending at an unmatched node on the right side. If you find one, flip all the edges along the path (matched ↔ unmatched), which increases the matching by 1. The DFS does exactly this: and someone in the comments used flow?? for finding the independent set. claude also says hopcraft karp can do it even faster: No, they're the same asymptotically for this problem. Hungarian: For each of V left-side nodes, run a DFS that's O(E). Total: O(V·E) = O(mn · mn) = O(m²n²). Edmonds-Karp (the max flow code): Each BFS finds one augmenting path in O(V+E) = O(mn). Max flow ≤ number of even-column seats = O(mn). So at most O(mn) augmentations × O(mn) per BFS = O(m²n²). Same thing. Both are doing the same work — finding augmenting paths one at a time — just using different traversal strategies (DFS vs BFS). If you wanted genuinely faster, Hopcroft-Karp finds multiple augmenting paths per phase and runs in O(E·√V) = O(mn·√(mn)), which for 8×8 doesn't matter but would for larger inputs.so is edmonds-karp max flow or different10:37 PMClarified Edmonds-Karp's relationship to Ford-Fulkerson algorithmClarified Edmonds-Karp's relationship to Ford-Fulkerson algorithmEdmonds-Karp is a max flow algorithm. It's a specific implementation of Ford-Fulkerson. The relationship: Ford-Fulkerson is the general method: repeatedly find augmenting paths from source to sink, push flow along them, until no more augmenting paths exist. It doesn't specify how to find the paths. Edmonds-Karp = Ford-Fulkerson but always uses BFS to find augmenting paths. This guarantees O(V·E²) worst case. If you use DFS instead, you get the naive Ford-Fulkerson which can be much slower (or even non-terminating with irrational capacities, though that's not relevant for integer problems). Other max flow algorithms that are fundamentally different: Dinic's — uses BFS to build a level graph, then finds all blocking flows in that level graph via DFS. O(V²·E). Faster than Edmonds-Karp in practice and in theory. Push-relabel — completely different paradigm, no augmenting paths at all. Pushes excess flow locally. O(V²·E) or O(V³) depending on variant. For bipartite matching specifically, Edmonds-Karp and Hungarian are doing essentially the same thing — finding augmenting paths one at a time. The naming is just which framework you think of it through: matching theory vs flow theory.
Drill Type:
Mindsolvere-read dp solution / peek at all the cached functions in code, re-read note about bipartate logic and max size independent set = total vertices - max matching
Solutions:
1293. Shortest Path in a Grid with Obstacles Elimination
Problem Summary:
We have an MxN (M,N <= 40) grid of spaces and walls and we want to reach the bottom right from the top left, moving any direction. We can eliminate at most K bricks. Min # of steps to reach the end?
Notes:
state is (r, c, bricksBroken) and we just do a normal BFS since we're counting steps. someone did a dp solution: [https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/solutions/2054300/bfs-is-for-losers-legends-make-dfs-work/?envType=problem-list-v2&envId=2c6bv1wh](https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/solutions/2054300/bfs-is-for-losers-legends-make-dfs-work/?envType=problem-list-v2&envId=2c6bv1wh) it's one of those where you set your dp state to infinity before recursing, then undo it, but honestly I think this might not be valid
Drill Type:
Mindsolvere-read notes, mostly worry about the bfs
Solutions:
970. Powerful Integers
Problem Summary:
Given X and Y and bound, find the # of numbers that are X^? + Y^? and <= bound
Notes:
Just iterate on powers, like log^2 time
Solutions:
974. Subarray Sums Divisible by K
Problem Summary:
Find the # of subarray sums divisible by K
Notes:
standard lop off
Solutions:
2435. Paths in Matrix Whose Sum Is Divisible by K
Problem Summary:
Find the # of paths in a grid going down and right where the path sum is divisible by K, grid size <= 4e5 and k <= 50
Notes:
dp(r, c, remainderK)
Solutions:
3144. Minimum Substring Partition of Equal Character Frequency
Problem Summary:
A string is balanced if every letter appears the same number of times, e.g. abbacc We have a string s with length <= 1000, find the minimum # of partitions of all balanced substrings
Notes:
For each dp(i) we try all j options as a partition, we can track in O(1) if its balanced by getting the frequency of letters in the loop, but also the frequency of frequencies
Solutions:
3148. Maximum Difference Score in a Grid
Problem Summary:
We have a grid of numbers N,M <= 1000 In a move we can go to the right or down, to any cell in that row or column, our score is that number - our current number We must make at least one move, max score?
Notes:
Basically for any number we just want to travel to the biggest number somewhere right/down of us, we can use dp to calculate what that number is
Solutions:
764. Largest Plus Sign
Problem Summary:
Given a binary matrix find the largest plus sign
Notes:
4 DPs which tell us how far to extend in different directions
Solutions:
3007. Maximum Number That Sum of the Prices Is Less Than or Equal to K
Problem Summary:
Honestly just read the question, but basically counting # of set bits across all numbers from 1 to N, sort of vibe
Notes:
Binary search on the answer For a given upper bound we check how many times each bit can occur, we can do this with digit dp we can either do dp(index, isTight, setBitsAccumulated, strNum) which returns the total number of set bits, or we can do dp(index, isTight, strNum) which returns both the total amount of numbers formable and the total amount of set bits But also there is a well known formula to understand how many times a set bit appears in all of 1 to num: cycle = 1 << (b + 1) full = num // cycle remainder = num % cycle count = full * (1 << b) + max(0, remainder - (1 << b) + 1) This is just the observation that bit b follows a repeating pattern of 2^b zeros then 2^b ones.
Drill Type:
Mindsolvere-read especially the bits thing, understand how that works
Solutions:
3070. Count Submatrices with Top-Left Element and Sum Less Than k
Problem Summary:
Count the # of submatrices starting at the top left that have sum of K
Notes:
Build a 2d range prefix query, could probably do with 1Ds also
Solutions:
2638. Count the Number of K-Free Subsets
Problem Summary:
We have N <= 50 numbers <= 1000. A subset is K-free if no two elements have a difference of K. How many subsets are K-free?
Notes:
One thought: For each number find its remainder mod k, those go into groups. So if k=3 then 1, 4, 10 might go into a group. Only numbers inside a group can collide with another, they cannot collide with elements from any other group. We can pick multiple numbers from a group as long as they don't differ by K. We could probably run some sort of dp on this (take a number, skip next if its adjacent, like if we take 1 we have to skip 4). We could also make the groups specifically chains that are K apart, so [1, 4] is its own group and [10] is a group. Then run a similar dp.
Drill Type:
Mindsolvere-read notes
Solutions:
3015. Count the Number of Houses at a Certain Distance I
Problem Summary:
We have N <= 100 houses. Each house is connected to adjacent houses. Also X and Y are connected. Find how many pairs of houses are exactly distance K.
Notes:
1/ Can BFS from every house which takes N^2 time 2/ Can floyd warshall in N^3 time (there is an n^2 variant but it might just be solution 3) 3/ For each pair just compute its distance with basic math, using and not using the X-Y pair My solution is the bad n^3 floyd warshall lol Part 2 question has a harder version I believe
Solutions:
2714. Find Shortest Path with K Hops
Problem Summary:
We have a graph of N <= 500 nodes and E <= 1e4 weighted edges. We want to go from the start to the end and we can skip up to K <= N - 1 edges. What is the min edge weight?
Notes:
Dijkstra but our states are (node, freeJumpsLeft) so instead of adding to the heap E times we add K*E times, I think this makes it EK log EK Vlad had some other SPFA algorithm but I think worst case complexity it would TLE
Drill Type:
Implementprobably implement a complex dijkstra, my leetcode submission solution probably isn't good so learn some cleaner ways
Solutions:
2941. Maximum GCD-Sum of a Subarray
Problem Summary:
Call the gcd sum of a subarray the gcd of its elements times its sum Given N <= 1e5 numbers arr[i] <= 1e6 Find the max gcd sum of any subarray of length K or more (K is given)
Notes:
For each left edge, note that our GCD can drop at most log(max) times, for a given GCD we want the max sum Binary search for each GCD range and use sparse tables to get the GCD, O(n log n log max) there is some more advanced solution that is n log (max) * log(log(max)): https://leetcode.com/problems/maximum-gcd-sum-of-a-subarray/solutions/4318908/short-no-binary-search-no-sparse-table-b-z8j5/ it feels conceptually pretty similar, didn't understand it though
Drill Type:
Mindsolvere-read notes
Solutions:
1016. Binary String With Substrings Representing 1 To N
Problem Summary:
Given a binary string, find if all numbers from 1 to N are present
Notes:
N is bounded so do multiple sliding window sizes
Solutions:
1019. Next Greater Node In Linked List
Problem Summary:
Given a linked list, for each node find the value of the next greater node
Notes:
Monostack, there is also some 1 pass (we don't need to convert the linked list to a stack first)
Solutions:
1047. Remove All Adjacent Duplicates In String
Problem Summary:
Given a string, remove duplicate letters
Notes:
There is some sort of O(1) two pointers solution in languages with mutable strings
Solutions:
1403. Minimum Subsequence in Non-Increasing Order
Problem Summary:
Get the minimum sized subsequence with sum greater than the sum of an array
Notes:
Sort and greedy, can bucket sort
Solutions:
2088. Count Fertile Pyramids in a Land
Problem Summary:
We have an NxN (N<=1000) binary matrix, count the # of fertile pyramids in it (see picture)
Notes:
The recurrence relationship is basically if the 3 points below us can all form fertile pyramids
Solutions:
1020. Number of Enclaves
Problem Summary:
Given a matrix grid of land and water, find the # of enclaves, an enclave is a land cell where we cannot reach the grid border
Notes:
Can just matrix DFS and determine if we have touched land
Solutions:
1031. Maximum Sum of Two Non-Overlapping Subarrays
Problem Summary:
Given an array of length N <= 1000 and two lengths len1 and len2, find the max sum of two non-overlapping subarrays with those two lengths
Notes:
We could use a dp(i, stage) sort of thing, also handle the order of len1 and len2 outside so do like fn(nums) and fn(nums[::-1]) Could also use prefix / suffix maxes with fixed sliding windows
Solutions:
1021. Remove Outermost Parentheses
Problem Summary:
Given a parentheses string, turn it into its primitive decomposition, and for each of those remove its outermost set of parentheses
Notes:
Could kind of use a stack and store the pieces in a result array, or track the indices we are going to delete
Solutions:
1022. Sum of Root To Leaf Binary Numbers
Problem Summary:
Given a binary tree with nodes being 0 or 1, find the sum of root to leaf paths in b inary
Notes:
Just shift the bits as we descend
Solutions:
1025. Divisor Game
Problem Summary:
Alice and Bob play a game starting with N <= 1000, taking turns, they can choose a divisor and turn N into N-divisor. If you cannot move you lose, who wins?
Notes:
Naive is DP, we can precompute all divisors for 1 to N in N log N time so we get N log N overall Observe that if you get 2 you win as you make 1 So if you have an even number you can always make an odd number (subtract 1), so even always wins
Solutions:
1026. Maximum Difference Between Node and Ancestor
Problem Summary:
Given a binary tree, find the max absolute value difference between any node and one of its ancestors
Notes:
Have the dfs return the min and max
Solutions:
1030. Matrix Cells in Distance Order
Problem Summary:
We have a matrix and a starting cell, return cells sorted by distance to the start
Notes:
Can just sort, use bucket sort, BFS out from the center (goes in a diamond pulsing pattern), or there may be a way to just do a spiral loop of sorts
Solutions:
1174. Immediate Food Delivery II
Problem Summary:
Given a SQL table of customer delivery orders, if a customer's earliest order time is the date as the time it was ordered, it is an immediate order, for each customer's earliest order find how many were immediate (I worded this poorly)
Notes:
There is a trick to get the earliest for each customer using DISTINCT with ORDER BY, after that we just use round
Solutions:
3087. Find Trending Hashtags
Problem Summary:
Given a SQL table of tweets report the top 3 hashtags in feb 2024
Notes:
We can grab the hashtag with regex, group by the hashtag, and order by the count
Solutions:
3657. Find Loyal Customers
Problem Summary:
Given a SQL table of customer transactions find all customers who have made at least 3 purchases, have <20% return rate, and have been active for at least 30 days
Notes:
Select + group by + multiple havings
Solutions:
2112. The Airport With the Most Traffic
Problem Summary:
Given a SQL table of flights which have the two airports and the # of flight count, find all airports with the max flights
Notes:
First make a vertical stacked table of airport + flight count by UNION ALL on the arrival and departure airports, note we write departure_airport as airport_id but we don't need to for the second select as it just puts it into the same column based on position Then select the sum of flight counts per airport id Then select any airport ID with a total equal to the max
Solutions:
883. Projection Area of 3D Shapes
Problem Summary:
We have a height map of buildings, find the sum of area of projections from the X Y and Z axes
Notes:
Basic math, look at maxes in rows, maxes in cols, and total buildings set (for Z projection)
Solutions:
892. Surface Area of 3D Shapes
Problem Summary:
We have a heightmap of towers, find the total surface area of this 3d map of buildings
Notes:
Basic math
Solutions:
1027. Longest Arithmetic Subsequence
Problem Summary:
We have an array of N <= 1000 numbers with values <= 500. Find the max length arithmetic subsequence.
Notes:
1/ We can do top down (i, requiredDiff) and loop on j indices that are specifically indices of nums[i] + requiredDiff This looks n*max(nums) * n complexity but maybe it amortizes? 2/ can do it in n*max(arr) dp where we have dp(index, requiredDiff) and then a second dp function which tells us the earliest occurence of a number in a range i… (or binary search instead of dp, but it's slower) 3/ Bottom up has a true N^2, we make dp[i][diff] the max # of elements we can use, with that diff, ending at the i-th index specifically To do bottom up we loop on i, then j<i, our dp depends only on previous j so this is a safe loop order. We look up the difference between the two elements and know which diff to recurse on.
Drill Type:
Mindsolvere-read notes and glance at code
Solutions:
2. Add Two Numbers
Problem Summary:
Given two linked lists, representing numbers, backwards, add them and return a backwards linked list of the sum
Notes:
Make a dummy node, handle carries, don't forget to add 1 to the end if there is still a carry
Solutions:
3567. Minimum Absolute Difference in Sliding Submatrix
Problem Summary:
We have an MxN M,N <= 30 grid and a K <= min(N,M). For each KxK region report the minimum difference between any two elements.
Notes:
Brute force works: For each top left corner we spend K^2 time gathering the elements and sorting them So N^2 times we spend K^2 to gather elements (N^2 K^2) and N^2 time we SORT K^2 elements, a single sort is K^2 log(K^2) So final TC is N^2 K^2 log K Sliding window optimization: We can do a 2d sliding window with sorted lists, one sorted containers holds the numbers and one holds the differences between adjacent elements. You might think we need to do a snake-like 2d sliding window (go right all the way, down 1, then left all the way, down 1, then right...) but a naive left->right, rebuild at 1 index down, left->right, etc works too For one pass we spend K^2 time building the initial window (We will do this N times across all top-rows, so that's N K^2). When we have our KxK we slide right by N, each time adding N elements and subtracting N elements, each of those taking log(K^2) time, so that's N^2 log(K^2) that we do N times, so like N^3 log K Also maybe something about an old driver tree which can query minimum absolute differences? not sure
Drill Type:
Mindsolvere-read notes on sorted list 2d window technique (rebuild KxK each top-row index still works)
Solutions:
3569. Maximize Count of Distinct Primes After Split
Problem Summary:
We have N <= 5e4 numbers <= 1e5 and Q <= 5e4 queries. Our queries update a number at an index, then we must choose some split of the array into a non-empty prefix and suffix such that the sum of counts of distinct primes in each part is maximum. For each query find the sum of those counts.
Notes:
Note that each prime spans a bar l...r with the min and max indices of that prime type. If we slice some i forming 0...i and i+1...n-1 we want that i to be in the range l...r-1. So we use a range add range max lazy seg tree to find a slice point which maximizes double slice scores, and that is also the # of primes we got 2 occurrences of, meaning the # of primes we got 1 occurrence of is just totPrimes - that. we use a sorted list or heaps to handle min and max indices of a prime type I also had this note: "we can use a normal [l, r] closed interval for the segment tree operations since no two ranges can share and endpoint, but the half open [l, r) for all operations works too"
Drill Type:
Mindsolvere-read notes, note the "points vs range trickiness tag" based on how we handle split points (l...r-1) for a prime type, splits are 0...i and i+1...r
Solutions:
3572. Maximize Y‑Sum by Picking a Triplet of Distinct X‑Values
Problem Summary:
We have two arrays X, Y length N <= 1e5. We want to pick three distinct indices that maximize Y[i] + Y[j] + Y[k] where X[i] != X[j] != X[k], find the max sum or -1 if not doable
Notes:
For each number-type in X get its max Y value, pick the top 3
Solutions:
1696. Jump Game VI
Problem Summary:
We have an array of N numbers, N <= 1e5, arr[i] <= abs(1e4). And K <= N. We start at i=0 and can jump forward up to K spots, wanting to reach the end. Our score is the numbers we land on. What is the biggest score we can get?
Notes:
Greedy isn't convincing, if there's any positive number in range sure we jump there but not sure how to handle negatives We can do seg tree dp for n log n, or even sorted list dp since we are doing a sliding window basically, or even heap dp. Deque dp is superior though (can do this with either monodeque or my two stacks queue technique)
Drill Type:
Mindsolvere-read notes, just be aware of all the types of dps we can do
Solutions:
1697. Checking Existence of Edge Length Limited Paths
Problem Summary:
We have an undirected graph with N,E <= 1e5 edges and Q <= 1e5 queries where each query [a, b, limit] is to know if there is a path from a<>b where every edge is < limit.
Notes:
Offline: Sort by increasing length and union find Online: We generate a normal MST that minimizes the total edge weight across the graph. This ALSO generates the minimax edge weight across all pairs of nodes. That is to say in our MST any simple path A<>B, the max weight on that path, is also going to be the smallest max weight on that path, in the graph. We can use jump tables for this. Proof: Consider an MST and some A<>B. It has some edge E on the path with max weight W. We claim we don't need that W to go from A to B, we can do it with some W' < W. Remove W from the MST. Now we have two components. To get from A to B we need to cross from the A component to the B component at some point in time, with some edge weight smaller than W. If that exists, it would form an MST with total weight < MST. Proof is complete. Semi proof of kruskal's: Say we consider connecting X and Y via some minimum weight edge E (after we sorted edges). X and Y are part of components. They're going to need to be connected somehow, either those components are directly connected or they grow in size later and connect from those extended regions, but at some point an edge will be added to connect the two components that contain X and Y, so why use that edge in the future with a higher weight.
Drill Type:
Implementprobably implement mst
Solutions:
1707. Maximum XOR With an Element From Array
Problem Summary:
We have N <= 1e5 numbers. We have queries and we need to for each query (x, m) find the max XOR of x against some number in our array where that number is <= m. Queries offline.
Notes:
Sort queries by increasing M, add to bit trie I also had this written: "there is a more advanced online version where each node in the trie also stores the minimum value inserted to reach that trie node, so we can iterate online"
Drill Type:
Implementimplement a bit trie, re-read advanced notes (maybe implement that?)
Solutions:
2592. Maximize Greatness of an Array
Problem Summary:
We have an array of N <= 1e5 numbers. We want to rearrange it into a new array nums2. Find the max # of indices where we can make nums2[i] > nums1[i]
Notes:
Sort the array Imagine a pointer on i=0 we need to beat i=0, iterate j until we beat it, now move on Can use sortedlist and greedily take the smallest number > X repeatedly too
Solutions:
E. Sum of Digits (and Again)
Problem Summary:
We have a function that takes a number, say 75, and gets its digit sum, repeats until we hit a 1 digit number, so 75123. We are given a string S of length <= 1e5, rearrange the characters to form some string which is a valid result from some starting X (tests are made so it is always possible)
Notes:
The first number can be at most 9 * 1e5 digit sum so we iterate on the sum of digits, for each one, we generate the resullting chain, and check if the leftover digits equal our sum. Note in my implementation I got burned since in python int and str actually take n^2 time on big numbers due to the way they were implemented.
Drill Type:
Mindsolvemental takeaways: -Consider iterating from the last backwards, but quickly discard due to combinatorial explosion -Try looking at each piece, if we look at the 2nd term it's easy to see it can only take on so many values so maybe test them all
Solutions:
D. Alternating Path
Problem Summary:
We have a graph of N <= 2e5 nodes with E <= 2e5 edges. We want to make each edge directed, then make it so paths alternate: Your task is to make a graph directed by choosing a direction for each edge. After directing the edges, call a sequence of vertices 𝑣1,𝑣2,…,𝑣𝑘 , where 𝑘 can be arbitrarily large and any vertex can be repeated any number of times, an alternating path if: the edge (𝑣1,𝑣2) is directed from 𝑣1 to 𝑣2 ; the edge (𝑣2,𝑣3) is directed from 𝑣3 to 𝑣2 ; the edge (𝑣3,𝑣4) is directed from 𝑣3 to 𝑣4 ; the edge (𝑣4,𝑣5) is directed from 𝑣5 to 𝑣4 ; and so on. Call a vertex 𝑣 beautiful if all paths (not necessarily simple) in the original graph that start at vertex 𝑣 are alternating in the resulting directed graph. What is the max # of beautiful vertices we can make after directing the edges?
Notes:
Imagine we 2-color a component. Going from white to black and black to white symbolize opposite edges. Everything has to be 2-colored in the component or the whole component fails. When we 2-color a component we choose the max color frequency as our beautiful ones. Note there are only 2 ways to 2-color a component (assuming it can be 2-colored).
Drill Type:
Implementimplement this bipartate which makes us do a lot of things (can it be 2-colored, handle multiple components, get the sizes of each half of the bipartate graph)
Solutions:
C. Spring
Problem Summary:
We have Alice Bob and Carol who visit the spring every A, 2A, 3A, ... B, 2B, 3B, ... and C, 2C, 3C... days, for up to M <= 1e17 days. If alone, they get 6 units of water. If two people, each get 3, if all three show up, each get 2 units of water. How much water does everyone get?
Notes:
Good inclusion exclusion practice, especially things like calculating exactly alice+bob is we exclude ABC from m//lcm(a,b)
Drill Type:
Implementshould implement to ensure understanding of all the different inclusions and exclusions
Solutions:
B. Right Maximum
Problem Summary:
We have an array of numbers with A[i] <= N and N <= 1e5, we repeatedly find the max element (if multiple, rightmost) and remove everything to the right of it including that max, how many times do we do this?
Notes:
Obviously can do a max seg tree and simulate or can map numbers -> indices, loop from max to min and count
Solutions:
A. Passing the Ball
Problem Summary:
We have people in a line who pass a ball left or right, line is like RRRRLRLLLRL (first is always R, last is always L) Then n times the students pass the ball starting at i=0, how many unique students get the ball?
Notes:
Can simulate or it goes to the first L
Solutions:
1715. Count Apples and Oranges
Problem Summary:
Given SQL tables of boxes which have apples/oranges and chests that could be inside boxes, also having apples/oranges, find how many apples and how many oranges there are in all the boxes
Notes:
We join the two (to ensure this chest is actually in one of our boxes) and SUM using coalesce to make it easy
Solutions:
1607. Sellers With No Sales
Problem Summary:
Given a SQL table of sellers and orders find all the sellers with no sales in 2020
Notes:
We just select the sellers where that seller isn't in a subquery of orders in 2020
Solutions:
1407. Top Travellers
Problem Summary:
Given a SQL table of users and rides report the total distance all users rode
Notes:
LEFT JOIN and SUM + COALESCE
Solutions:
449. Serialize and Deserialize BST
Problem Summary:
We muts serialize and deserialize a BST
Notes:
Since it is a BST all node values are unique, we could just store children maps or parent maps and do it Probably some other "more efficient" ways like traversing a BST in some uniquely serializable way
Solutions:
2569. Handling Sum Queries After Update
Problem Summary:
We have a binary array of length N <= 1e5, and a second array of the same length, we must support these operations: -range XOR that binary array -for each index in nums1, add nums1[i] * p to nums2[i] (p is given in the query) -report the sum of nums2
Notes:
Basically we can just do range XOR on nums1 and range count the # of bits in nums1 since we only care about the TOTAL sum of nums2 we use a lazy seg tree which has a lazy tag "flipped" and we want nodes to store how many 1s are in it, and also the node width since it makes the implementation easier We could also simulate with a bitset which is n*q / W which is slower
Drill Type:
Mindsolvere-read notes / peek at lazy seg tree lambdas
Solutions:
1621. Number of Sets of K Non-Overlapping Line Segments
Problem Summary:
Given N points from 0 to N-1, we want to put K segments each of width >= 1, such that no two overlap, but they can share points. How many ways can we do this?
Notes:
Easy dp is dp(i, placed, open) and we handle all the states like open, close, closeAndOpen, etc, this is O(n*k) There is a goated linear solution though: If we have K segments we are going to have K+1 divisors, call a divider D and the segment S, for instance with 2 segments we will have: D S D S D D can be >= 0 (for instance on the ends, or "dividing" two segments that touch) But S must be >= 1 The total sum of these widths must be N-1 D+S = 2*K + 1 Now imagine each of these D+S things is a bin, we must distribute N-1 segment pieces into them "but wait, we can't just put random segment pieces together since 0<>1 cannot be in the same bin as 4<>5 if they're disconnected?" The idea is that this chain: (s=spacer here, x=segment) s₀=0 x₁=2 s₁=0 x₂=1 s₂=0 sum: 0+2+0+1+0 = 3 ✓ s₀=0 x₁=1 s₁=0 x₂=2 s₂=0 sum: 0+1+0+2+0 = 3 ✓ s₀=1 x₁=1 s₁=0 x₂=1 s₂=0 sum: 1+1+0+1+0 = 3 ✓ s₀=0 x₁=1 s₁=1 x₂=1 s₂=0 sum: 0+1+1+1+0 = 3 ✓ s₀=0 x₁=1 s₁=0 x₂=1 s₂=1 sum: 0+1+0+1+1 = 3 ✓ Is basically tracking how many segments get eaten from the left So this ends up being equivalent to stars and bars "identical balls" but not super convinced yet Also since a S must be >=1 but stars and bars allows 0-ball bins we do math substitution Just algebra. Start with the original equation: s₀ + x₁ + s₁ + x₂ + s₂ = 3 where x's ≥ 1, s's ≥ 0. Replace x₁ with d₁ + 1, replace x₂ with d₂ + 1: s₀ + (d₁ + 1) + s₁ + (d₂ + 1) + s₂ = 3 Simplify — the two 1's come out: s₀ + d₁ + s₁ + d₂ + s₂ + 2 = 3 s₀ + d₁ + s₁ + d₂ + s₂ = 1 That's it. Five variables, all ≥ 0, sum to 1. Stars and bars applies directly. In general: k segments each contribute a -1, so the sum drops from n-1 to n-1-k. The number of bins stays at 2k+1.
Drill Type:
Mindsolvere-read notes, kind of be aware more of the stars and bars idea
Solutions:
3106. Lexicographically Smallest String After Operations With Constraint
Problem Summary:
We have two strings, we can change a letter to another in 1 operation, can also loop around, find the smallest lexicographical string we can make from an input string with K operations
Notes:
go letter by letter, best way to implement is if we can wrap up to A, via Z, that is one option, otherwise, we always just descend down, this basically makes the logic quite easy
Solutions:
2378. Choose Edges to Maximize Score in a Tree
Problem Summary:
We have a weighted tree, we can take edges as long as no two touch, find max edge weight sum
Notes:
We can do dp(node, didTakeParent), nice implementation problem, technically don't need the dp can just do a postorder dfs
Drill Type:
Implementgood implementation test
Solutions:
3615. Longest Palindromic Path in Graph
Problem Summary:
We have N <= 14 nodes in a graph, each node has a letter, find the longest palindromic path
Notes:
dp(i, j, takenMask) and we loop on i's neighbors and j's neighbors is n^4 * 2^n (even though it looks like for a given taken mask, we can only have 4 combos of i and j, we cannot) This somehow passed in time, its 6e8 I guess there's just very few states
Drill Type:
Implementgood practice to implement here, we update the score, when do we do it? in the dp itself, before we recurse? I kept making mistakes
Solutions:
3873. Maximum Points Activated with One Addition
Problem Summary:
Given N <= 1e5 (x, y) <= 1e9 points, if one point is activated, any other point on the same x or y line gets activated (this repeats over and over). We have this graph of points and we can activate one initial point, what is the most number of points we can activate in total?
Notes:
First connect all the points with union find or DFS Then note that two components can never share an X coordinate, so when we place our point at some X address it can only touch one component. We want to pick some Y ideally the one with the second biggest group (we can never connect more than 2 groups on X or Y, again, because they would be connected), we can always connect the second biggest since that point (x,y) cannot be taken, so answer is top two biggest
Solutions:
3872. Longest Arithmetic Sequence After Changing At Most One Element
Problem Summary:
Given an array of N <= 1e5 numbers, we can change one and need to find the longest subarray that is an arithmetic sequence, find this length
Notes:
We can do prevDp(i) and suffDp(i) to compute how long we can go in one direction, I included the diff in the parameter prevDp(i, diff) even though it is only one Now we iterate and for an element if we change it we can form a midpoint between nums[i-1] and nums[i+1], or attach to just one of the ends There is some two pointers technique I did not learn
Solutions:
3871. Count Commas in Range II
Problem Summary:
Count the # of commas in all numbers from 1 to N, N <= 1e15
Notes:
We can use math or digit dp
Solutions:
3870. Count Commas in Range
Problem Summary:
Find how many commas occur in numbers <= 1e5
Notes:
just loop and count, harder version with math or digit dp
Solutions:
104. Maximum Depth of Binary Tree
Problem Summary:
Find the max depth of a binary tree
Notes:
standard dfs returns depth
Solutions:
3652. Best Time to Buy and Sell Stock using Strategy
Problem Summary:
We have stock prices over time and actions (buy, sell, hold). A strategy is where we select K consecutive days and turn the first half into holds and the second half into sells. The profit is the total profit across all days (all operations are considered legal). Find the best strategy profit.
Notes:
Fixed sliding window + prefix sums
Solutions:
3004. Maximum Subtree of the Same Color
Problem Summary:
Find the largest subtree of a tree where every node is the same color
Notes:
We can do it in one dfs where the dfs returns the size and if every node is the same color
Solutions:
1325. Delete Leaves With a Given Value
Problem Summary:
We have a binary tree, delete all leaves with the value 'target'. Note if we delete a leaf and its parent is now a leaf and has that value it should get deleted too.
Notes:
We basically want to delete entire subtrees of leaf based values, a nice implementation question
Drill Type:
Implementshould test my implementation here / read notes after because it tells a good way
Solutions:
2697. Lexicographically Smallest Palindrome
Problem Summary:
We have a string of letters and we can replace one letter in one operation, we want to make it a palindrome, particularly the smallest lexicographical palindrome, using the fewest number of operations
Notes:
Basically every mismatched pair we set to the minimum of the two letters
Solutions:
https://leetcode.com/problems/find-the-maximum-length-of-valid-subsequence-i/description/
Problem Summary:
We have an aray of numbers N <= 2e5, nums[i] <= 1e7. A subsequence is valid of the parity of sums of all two adjacent elements is the same. Find the longest valid subsequence.
Notes:
We basically have 4 patterns: -all numbers even -all odd -even, odd, even, odd, etc -odd, even, odd, even, etc My implementation was very clear, test each pattern and infer the required one from the count we have taken so far, did a bottom up dp
Drill Type:
Mindsolvere-read code since it is very clean
Solutions:
3258. Count Substrings That Satisfy K-Constraint I
Problem Summary:
Find how many substrings of a binary string have at most K 0s and K 1s, but N is small
Notes:
brute force
Solutions:
1396. Design Underground System
Problem Summary:
We need to support a class where customers can check in with an ID at a station at a certain time, check out at a time, and we can report the average time to go from a start to an end station
Notes:
We can basically track all of this in hashmaps
Solutions:
949. Largest Time for Given Digits
Problem Summary:
Given 4 digits, find the latest 24-hour time using each digit once
Notes:
Try all combos and have a validator function Or even brute force all times and check if it can be formed with our digits lol
Solutions:
1522. Diameter of N-Ary Tree
Problem Summary:
Find the longest diameter of an N-ary tree
Notes:
DFS and send up the depth chains, and iterate over the biggest 2
Solutions:
2085. Count Common Words With One Occurrence
Problem Summary:
Given two string arrays words1 and words2, return the number of strings that appear exactly once in each of the two arrays.
Notes:
just do what it says
Solutions:
1072. Flip Columns For Maximum Number of Equal Rows
Problem Summary:
We have a binary matrix and can flip columns, find the max # of rows all equal
Notes:
Basically find the most common occurrence of a row + its inverted row together
Solutions:
1804. Implement Trie II (Prefix Tree)
Problem Summary:
We want to build a trie which can insert words, count words equal to X, count words starting with X, and erase a word
Notes:
Each node can store the prefix count and the ending word count so we can easily query these quickly, we could even store a counter map of word->frq to make count words equal to O(1) instead of descending the trie (my implementation was bad I dfs'd to count prefixes, once I got to that node)
Drill Type:
Implementprobably implement a trie especially the delete to stay fresh on good implementation
Solutions:
1765. Map of Highest Peak
Problem Summary:
We have an NxM (N,M <= 1000) grid of cells. Some are water which are 0. Land cells can differ from adjacent cells by at most 1. What is the highest peak we can make?
Notes:
Multisource BFS from water, a land cell can be at most the closest it is to any water a node can be its min distance to water, need to think more about a proof but this is obvious intuition We can also do a 2-pass dp, find the closest water up and left, and down and right, and min the two
Solutions:
2280. Minimum Lines to Represent a Line Chart
Problem Summary:
We have a stock chart, find the # of unique lines needed to represent it (see picture)
Notes:
Count slope changes
Solutions:
1427. Perform String Shifts
Problem Summary:
We are given a string and a list of shift operations (rotate left by X, right by Y, etc) return the final string
Notes:
Tally up shifts and do it at the end
Solutions:
3290. Maximum Multiplication Score
Problem Summary:
We have an array of length 4 and a second array of length N <= 1e5, our score is a[0] * b[i0] + a[1] * b[i1] + a[2] * b[i2] + a[3] * b[i3] find the max score
Notes:
dp(i, j) is 4n
Solutions:
1616. Split Two Strings to Make Palindrome
Problem Summary:
We have two strings A and B, pick a split point and we get either a_prefix + b_suffix or b_prefix + a_suffix and see if it makes a palindrome
Notes:
Greedy solution where we try to match prefix + suffix as much as possible for each (a,b) and (b,a) order and the middle part we can take from either string if it is a palindrome. Also can do cursed hashing thing where we can literally construct the hashes and check if it is a palindrome
Drill Type:
Mindsolvere-read code, particularly my implementation for the greedy where I do check(a,b) or check(b,a) but ALSO need to check two mids, there's basically 4 cases, which is take a prefix of A or take a prefix of B, but within one of those cases we take a small prefix (up to the match point) of A and the rest suffix from B, or a big prefix from A and a small suffix of B. Basically if we take some prefix and suffix that are mirrors, the middle part could come from just one of them (just the prefix, just the suffix) and that itself could be a palindrome, but that middle part could come from either side too.
Solutions:
2246. Longest Path With Different Adjacent Characters
Problem Summary:
We have a tree where each node has a letter, find the longest path where no two adjacent nodes share a letter
Notes:
The dfs sends up a chain length, we iterate over children and pick the biggest 2
Solutions:
778. Swim in Rising Water
Problem Summary:
We have an NxN N<=50 grid of heights. We start at the top left and must reach the bottom right. Water is rising and we can reach a tile if the height of both tiles is <= water height. What is the min # of time to reach the end?
Notes:
1/ Binary search on the answer, then dfs to see if we can reach the bottom right 2/ Basically store the frontier of new cells in a min heap, keep popping until we reach the bottom right, this is just Dijkstra lol 3/ We could also union find minimum cost edges (edge cost is the max of the two cells) until the top left and bottom right are connected, it's kind of an MST
Drill Type:
Implementimplement the dijkstra
Solutions:
1493. Longest Subarray of 1's After Deleting One Element
Problem Summary:
Find the longest subarray of all 1s in a binary array after deleting 1 element
Notes:
Can use a sliding window and shrink while we have 2 ones, update result with r-l not r-l+1 can use prefix + suffix dp too
Drill Type:
Implementhonestly good to implement the window because the r-l instead of r-l+1 trick is cool
Solutions:
3661. Maximum Walls Destroyed by Robots
Problem Summary:
We have N <= 1e5 robots each at some position <= 1e9. We have N <= 1e5 walls also at positions <= 1e9. Each robot can shoot one bullet either left or right and its bullet can travel distance[i] <= 1e5. If a bullet hits a robot the bullet stops. Find the max # of walls we can hit.
Notes:
Sort the robots and handle left to right. We use dp and check if the previous robot shot right or left so we basically have 2N states, a bit of implementation to not double count things (I used sorted lists to count in range (a, b)), could use binary search or even a sliding window I think, some sort of monotonic property lets us not binary search
Solutions:
642. Design Search Autocomplete System
Problem Summary:
We have a list of sentences and how many times they have been typed before. We will get new letters one at a time representing a prefix of a sentence being built up. At each prefix, report the top 3 most frequent sentences that previously were typed with this prefix. Once the sentence we are typing is done a # character will appear denoting we reset.
Notes:
Trie where each node stores its top 3. As we input one letter at a time we track the current node and sentence build-up in a class variable. We report the top 3 in our current node and move to the next node. When we hit # we add the entire sentence to our frequency map and update the frequencies of every trie node anew, and reset our built up sentence.
Solutions:
3621. Number of Integers With Popcount-Depth Equal to K I
Problem Summary:
Given a #, take its number of set bits, we get a new number, repeat until we hit 1, this is the "depth". How many numbers have a depth of K <= 5, and are <= 1e15?
Notes:
Standard dp(i, setBits, tight) and we use a second depth function at the base case
Solutions:
3869. Count Fancy Numbers in a Range
Problem Summary:
A number is fancy if its digits are strictly increasing, strictly decreasing, or the sum of its digits is one of those. Find the # of fancy numbers in the range L...R (R <= 1e15).
Notes:
Standard digit DP dp(strNumber, i, tight, leadingZeroes, goingUp, goingDown, digitSum) There is also a digit dp + inclusion exclusion idea: -Find all numbers that are fancy by virtue of their digits being strictly increasing or decreasing (this is small, like a few thousand) -Find all numbers that are good purely due to their digit sum (easier digit dp) -Exclude the ones good by the number itself being increasing/decreasing, if its digit sum is also fancy
3868. Minimum Cost to Equalize Arrays Using Swaps
Problem Summary:
We have two arrays, we can do this: -Swap two elements in an array (free) -Swap two elements at the same index, across the two arrays (cost 1) What is the min cost to make them equal? Or -1 if impossible
Notes:
First validate every number has even total frequency Then for each number check the difference, say we have: [2, 2] and [1, 1] our diffs are both 2 When we pay 1 we fix 4 diffs, so its just TOT_DIFFS // 4
Solutions:
3867. Sum of GCD of Formed Pairs
Problem Summary:
Honestly just a bunch of dumb instructions we basically do to simulate it's quite easy
Solutions:
3866. First Unique Even Element
Problem Summary:
Find the leftmost number in an array that is even and has a frequency of 1
Notes:
make frequency map then scan
Solutions:
1563. Stone Game V
Problem Summary:
Given an array of length <= 500, we divide it into two subarrays. We score the smallest subarray + the recursed problem on that subarray. If the subarray sums are equal we pick which one. What is our max score? Game ends with 1 element in a subarray.
Notes:
O(n^3) passing naive dp Naive dp is dp(l, r) recurse on all split points. O(n^2 log n) binary search + pref + suff dp Note that for some groups l...a l...b l...c we are going to gain that score and recurse on dp(l, a) or dp(l, b) or dp(l, c) After some point when the l...x sum becomes too big, we start scoring x+1...r instead We could binary search for this split point, then take a pref and suff dp which is the maximum subarray sum + dp sum in that prefix or suffix range This can be done top down or bottom up (see code) O(n^2) dp with monotonic property I think (didn't implement) if we fix L and increment R, the split point only monotonically moves, so we could avoid the binary search. But instead of looping on length as our outer for loop now we loop on the left edge. I think we could also precompute these points and then still do top down
Drill Type:
Implementre-read notes, implement n^2 log n at least bottom up if not top down too
Solutions:
3619. Count Islands With Total Value Divisible by K
Problem Summary:
Given a matrix graph, count the # of islands with a value-sum divisible by k
Notes:
Just dfs and track the sums
Solutions:
1081. Smallest Subsequence of Distinct Characters
Problem Summary:
Given a string of N <= 1e3 letters, find the lexicographical smallest subsequence that contains every letter
Notes:
increasing monostack, we pop while we are smaller (since we want smaller letters to go left) and there is more of that letter to the right, O(1) space since stack / set hold O(26) we could also solve letter by letter, find the smallest first letter we can use where every other letter appears on the right, repeat this process same as question 316 did not drill since I drilled 316
Solutions:
316. Remove Duplicate Letters
Problem Summary:
Given a string of N <= 1e4 letters, find the lexicographical smallest subsequence that contains every letter
Notes:
increasing monostack, we pop while we are smaller (since we want smaller letters to go left) and there is more of that letter to the right, O(1) space since stack / set hold O(26) we could also solve letter by letter, find the smallest first letter we can use where every other letter appears on the right, repeat this process same as question 1081
Drill Type:
Mindsolvere-read notes
1044. Longest Duplicate Substring
Problem Summary:
Given a string of length N <= 3e4, find the longest substring that occurs more than once.
Notes:
Binary search on answer, for a given answer, do a fixed window + rolling hash to compute it if occurs some other ideas I don't know (claude): Suffix Array + LCP Array — This is probably the most elegant. Build the suffix array (sorted order of all suffixes), then compute the Longest Common Prefix array between adjacent suffixes. The answer is just the max value in the LCP array. Building the suffix array can be done in O(n log n) or O(n) with SA-IS, and the LCP array in O(n) with Kasai's algorithm. So the whole thing is O(n log n) or even O(n). Suffix Automaton (SAM) — Build the suffix automaton in O(n), then find the longest state that has endpos set size ≥ 2 (i.e., the substring occurs at 2+ positions). The length of that state's longest string is your answer. This is O(n) total but the constant factor and implementation complexity are higher. Suffix Tree — Build Ukkonen's suffix tree in O(n). Any internal node (non-leaf) represents a substring that occurs multiple times. The deepest internal node (by string depth) gives you the longest duplicate substring. Conceptually clean but Ukkonen's is notoriously annoying to implement. Binary Search + Suffix Array (no hashing) — You can binary search on length L, then check if any two suffixes share an L-length prefix by looking at the sorted suffix array. This avoids hash collisions entirely. O(n log²n) with a naive suffix sort, or O(n log n) if you use a proper suffix array construction. Among these, suffix array + LCP is the go-to competitive programming approach for this class of problems — it's the best balance of speed, reliability, and implementation effort. If you've been meaning to add SA + LCP to your template library, this problem is a solid one to do it on.
Solutions:
3287. Find the Maximum Sequence Value of Array
Problem Summary:
We have an array of numbers, N <= 400, arr[i] < 2^7. We need to pick a subsequence of length 2*k, k <= N/2. The score of our subsequence is going to be like this: (seq[0] OR seq[1] OR ... OR seq[x - 1]) XOR (seq[x] OR seq[x + 1] OR ... OR seq[2 * x - 1]) Basically the first half ORd together, XOR the second half ORd together Find the max score
Notes:
I tried dp(i, seqI, mask) but it doesn't really work because once we reach the second half of our subsequence, we can unset bits in the mask, but after we unset it once, we might set it again, basically we need dp(i, seqI, mask1, mask2) which is too many states. Instead we compute for each prefix all the ORs doable, and for each suffix, and we loop on those two at each split point and find the highest XOR. So we need pref(i, seqI) which stores a bitmask of doable ORs. Meaning (1<<5) means an OR of 5 is doable (this ends up feeling a bit wonky). Same with suff. Easy top down but I wanted bottom up. Bottom up I normally do things like pref[i] is responsible for 0...i but that's annoying because when we recurse on pref[i-1] in the knapsack I need to add edge cases. The true best way is to make pref[i] be responsible for the first i elements, so 0...i-1, and start our loop on i=1. This also means we do nums[i-1] in the knapsack loop. Now we never look back at pref[-1]. But for suffixes it works differently. We do suffix[i] is for i...n-1 because we can look right. For instance suff[n-1] looks at suff[n] which is our extra padded base case. I also tried suff[i] is responsible for the last i elements but that makes it confusing.
Drill Type:
Implementre-read notes, implement MLG bottom up dp
Solutions:
2065. Maximum Path Quality of a Graph
Problem Summary:
Given a graph of N <= 2000 nodes and E <= 2000 edges, each node has a value and each edge has a weight. We start a path from 0 and must end at 0 (repeat nodes allowed). The score is the sum of values of unique nodes along our path. Find max score with a total path weight <= a given weight. Note each edge has at most 4 edges and the max weight is <= 100, and the min edge weight is >= 10.
Notes:
We have at most 10 edges walked so 4^10 complexity. Just dfs.
Solutions:
1062. Longest Repeating Substring
Problem Summary:
Given a string length N <= 2000, find the length of the longest substring that occurs at least twice.
Notes:
O(n^2 log n) - binary search + set Binary search on the answer, for each possible answer slide a fixed window of that size extracting the substring and check if it exists in the set. n^2 for this check. O(n log n) - binary search + rolling hash Do the same must store hashes so the check is O(n) O(n^2) dp - dp(i, j) is the longest start we can make from i... and j... O(n^2) MSD Radix sort - not sure O(n^2 log n) suffix array with sorting, not sure - according to claude O(n log n) suffix array, according to the editorial, combines with LCP array? O(n) ukkonen's alg
Solutions:
91. Decode Ways
Problem Summary:
We have a string of numbers like '123' which decodes to text. For instance ABC (1->A, 2->B, 3->C) or LC (12->L, 3->C). Find the # of unique decodings.
Notes:
Basic dp, can do bottom up or top down O(1) space
96. Unique Binary Search Trees
Problem Summary:
Given N <= 1e9, compute the # of unique BSTs
Notes:
dp(l, r) with a for loop for the root works. Naive upper bound is n^3. Not sure if true work is faster here. Also the answer is the n-th catalan number which we can compute in O(n)
Solutions:
95. Unique Binary Search Trees II
Problem Summary:
Given N <= 8, return all structurally unique BSTs with the numbers 1...N
Notes:
For a given number range L...R we can pick a root and recurse on the subproblem. I used DP but a naive recursion works too, a bit confusing to reason about the complexity between those. Note the # of unique BSTs with N nodes is G(n) where G is the n-th catalan number. The dp is storing a list of trees in the values
Solutions:
97. Interleaving String
Problem Summary:
We have three strings, s1, s2, s3. Find if s3 can be constructed from an interleaving of s1 and s2. s3 <= 200
Notes:
Standard dp(i, j) for n^2 Don't think there's a bitset dp
Solutions:
1456. Maximum Number of Vowels in a Substring of Given Length
Problem Summary:
Find the max # of vowels in a substring of length K
Notes:
Standard fixed window
Solutions:
484. Find Permutation
Problem Summary:
We have a string of I and D denoting increasing and decreasing. For instance "DI" means we need to form a permutation where perm[0] -> perm[1] decreases, and perm[1] -> perm[2] increases, like [2, 1, 3]. For a given string, find the lexicographically smallest permutation. N <= 1e5.
Notes:
Tricky problem, intuitively we want to place the smallest number we can at each index. I tried decomposing into blocks like [I, I, DDD, I, DD] and when we encounter some chain of Ds we descend like 9 8 7 but my implementation kept running into edge cases that didn't quite work. A cleaner way of doing this is to start with the permutation [1, 2, ... N] and then loop on this, when we hit a decreasing block we need to reverse a section. For instance a chain of 3 Ds is responsible for 3 gaps, so 4 elements, reverse those. I left my old comments / code in trying other stuff and some examples for instance why a basic greedy doesn't work. There was also a stack and a two pointers solution I did not understand.
Drill Type:
Mindsolvereview working code
Solutions:
1124. Longest Well-Performing Interval
Problem Summary:
We are given an array of hours worked per day, of length <= 1e4. A day is tired if it has >8 working hours. Find the longest interval where the # of tiring days is > the # of non-tiring days.
Notes:
If we re-map this to prefix sums of tiring days, this is basically finding the longest "ramp", (i,j) with i<j and nums[j] > nums[i]. Thus, we can solve it with all 4 solutions listed in in my notes for 962. Maximum Width Ramp, which I will not duplicate here. The one solution I used myself was binary search + prefix mins: # O(n log n) solution 1 # remap to +1 means tired and -1 means rested # for a given R we have some surplus, say +3 means 3 tired # we can cut off at most +2 from the left, and we want the leftmost one <= 2 # so binary search for leftmost prefix with a min <= 2
Drill Type:
Mindsolvere-read notes, basically max width ramp
Solutions:
962. Maximum Width Ramp
Problem Summary:
A ramp is a pair (i, j) with i<j and nums[i] <= nums[j]. Find the maximum width ramp.
Notes:
4 solutions, see code for more details: 1: O(n log n) binary search + prefix min. For each index, consider it the right edge, binary search for the leftmost left edge with a prefixMin <= nums[j]. Or use segment tree on values where each value stores the smallest index, then do a prefix range query [0, nums[j]] 2: O(n log n) tricky sorting. Sort (value, index) in increasing order. Loop through this tracking our minimum previous index. 3: O(n) tricky two pointers. Initialize l=r=0 and set up a suffix max array. While nums[l] <= suffMax[r] we increment r and update result with r-l. If we cannot, we increment l. Code has a bit more notes here but I haven't fully convinced myself of this 4: O(n) stack, but not the "find next closer smaller element" type of thing. Note only some left candidates matter, particularly those in decreasing value order. Put these in a "stack". Then loop backwards over them popping while we have a valid ramp.
Drill Type:
Mindsolvereview all solutions
Solutions:
Corner Subgrid Count
Problem Summary:
We have an NxN (N<=3000) binary grid. Find the # of subgrids where all 4 corners are 1s.
Notes:
Enumerate pairs of rows (n^2), for each one do a bitwise AND to find how many shared bits there are and use basic combinatorics after that. O(n^3/W). Some good lessons on bitsets here: A bitset is implemented with a fixed size. If we left shift, things drop out the left side. Remember a bitset is basically an array of words and we can toggle bits in O(1) because we know which word to affect. If we allow true shifting of words then we lose this capability. Here are some bitset operations: AND, OR, XOR, NOT: These are all N/64 because we just loop through every word and do a single machine instruction. Set a bit, flip a bit, that stuff is O(1) since we access the word directly. Shifting is also N/64: Validated bitwise shifting mechanics and reconciled O(n/w) complexityLet's say you have words W[0], W[1], W[2], ... where W[0] is bits 0–63, W[1] is bits 64–127, etc. Shift left by 5 means every bit moves from position p to position p+5. For the new W[i], where do its bits come from? Most come from the old W[i] shifted left by 5. But that vacates the bottom 5 bits — those come from the top 5 bits of W[i-1] that got "pushed out." So it's just one pass: for i from high down to 1: new_W[i] = (W[i] << 5) | (W[i-1] >> 59) new_W[0] = W[0] << 5 Find first set bit is N/64 too. Loop over every word, for a given word we find the first set bit with __builtin_ctzll (count trailing zeros) which is a single CPU instruction. I think find_next is the same in the sense we can repeat this over and over starting from where we left off type of thing but don't have full understanding here. Counting # of bits in a word is O(1) since it is a single machine op, so counting in a bitset is N/64. For this problem we needed to count bits in the AND result which if we use a pragma directive makes it a true O(1) machine instruction. Otherwise it uses some jank software trick which is still O(1) but worse: x = x - ((x >> 1) & 0x5555555555555555); x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F; return (x * 0x0101010101010101) >> 56; This counts bits by summing adjacent pairs, then groups of 4, then 8, etc. — like a reduction tree. Still O(1) but several instructions instead of one. That's exactly what the compiler emits when you use __builtin_popcountll without #pragma GCC target("popcnt") — and why that pragma matters so much.
Drill Type:
Mindsolvere-read notes on bitsets
Solutions:
835. Image Overlap
Problem Summary:
We have 2 N x N binary grids, where N <= 30. We can overlap them at different translations. Find the largest amount of 1 overlapping
Notes:
O(n^4) brute force seems optimal time complexity
Solutions:
3385. Minimum Time to Break Locks II
Problem Summary:
We have N <= 80 locks. Each requires energy <= 1e6 to break. We have a sword of energy 0. Every turn our energy increases by X (initially X=1) and if we break a lock we reset to 0, but X increases by 1. Find the minimum # of time to break all locks.
Notes:
We basically have a cost matrix of order <> lock and need to assign one order to each lock. So hungarian works. Counter example for why greedy doesn't work: # greedy that doesnt work # # 30, 40, 40, 45 # # FAILS because when we have (40, 45) left and gain 3 per minute, we could wait 14 min and break 40, then 12 min and break 45 with our greedy, but optimally we wait 15 min and break 15, then 10 and break 40
Drill Type:
Implementimplement hungarian from scratch
Solutions:
222. Count Complete Tree Nodes
Problem Summary:
Given the root of a complete binary tree, find how many nodes are in it, in < O(n) time. A complete binary tree is one where every level, except possible the last, is filled entirely. The last one is filled left to right.
Notes:
First find the depth by going left all the way. Now we have a bounding range. Now we binary search on the answer. We want to detect if say node 100 (with normal labels, 1 for root, 2 left child, 3 right child) exists. We generate the required path backwards, cause if we use 1-indexed labels the parent is always label//2. Then we walk forwards to see if it exists.
Drill Type:
Mindsolvere-read notes particularly about the ID walking technique, can peek at code if needed
Solutions:
2876. Count Visited Nodes in a Directed Graph
Problem Summary:
Given a functional graph, compute the # of nodes we walk down until we hit a repeat node, starting at each path
Notes:
1/ Can do cycle detection then use DP until we enter a cycle. To detect cycles I use both a seen and a path set, just one is not enough because maybe we have 1->2->3 and we process 3 then 2 then 1 we are going to terminate early but it doesn't mean we hit a cycle 2/ Topo sort, start with nodes with in-degree 0, once done removing then anything else is in a cycle
Drill Type:
Implementcode both cycle detection + dp, and topo sort
Solutions:
900. RLE Iterator
Problem Summary:
A run-length encoding is just pairs of frequency, number, e.g. [8,8,8,5,5] -> [3, 8, 2, 5]. Also, [1, 8, 2, 8, 2, 5] is a valid encoding. Given a run-length encoding, create the implementation for next(n) which exhausts that many numbers and returns the n-th one.
Notes:
Basically just track a pointer, note that we cannot exhaust one at a time, we want to exhaust up to N in one index if possible It's not exactly two pointers but I'm kind of tagging it as such
Solutions:
164. Maximum Gap
Problem Summary:
Given an array of N <= 1e5 numbers, arr[i] <= 1e9, find the maximum distance between any two numbers, in O(n) time.
Notes:
The smallest possible maximum distance can be computed based on the min and max. So we make buckets of those max distances. The answer is either the max-min of a single bucket, or min-max of different buckets. Implementation is a bit tricky (turning a number -> its bucket ID), realizing we can skip over buckets like bucket 3 min minus bucket 1 max could be doable. NOTE: I don't think my implementation really correctly understood the idea of the pigeonhole principle because we should only need to compare elements in different buckets.
Drill Type:
Implementre-code the answer at some point to test ability to turn number -> bucket ID
Solutions:
481. Magical String
Problem Summary:
A magical string consists of 1s and 2s and as we read the lengths of the groups of the blocks of 1s and 2s it forms itself. For example 122112 is the start of it. The groups are |1| 22 | 11 | 2 Lengths are 1, 2, 2, 1 which is the start of that string Find how many 1s are in the first N <= 1e5 characters
Notes:
We seed the string with [1, 2, 2] and we know the next digit we are placing is a 1 as the blocks alternate. We know the length we read is at i=2. So we just use a pointer to read and then update the array. Seeding with first 3 makes it easier didn't deeply understand why
Drill Type:
Mindsolvere-read notes / code
Solutions:
3130. Find All Possible Stable Binary Arrays II
Problem Summary:
We are given `zero` <= 1000, `one` <= 1000, and `limit` <= 1000. We want to make binary arrays of length zero+one. It should have zero 0s and one 1s. But it cannot have more than limit consecutive numbers of the same type. How many ways can we do this?
Notes:
A naive DP: dp(zeroesPlaced, onesPlaced, lastBit) for newBitPlaced in range(limit+1)... This is n^3 time which is too slow. But we can use a prefix sum to speed it up. I had working python cached for_loop trick using the suffix sum technique. Bottom up dp I used pull which is a prefix sum of previous states. So we loop over the new states (newTotalZeroes, newTotalOnes) and prefix sum the previous states based on how many in a row we place. Push DP seems complex because at a state we need to apply a range update to future states not sure how. The pull was a bit complex. We did not need NDP since we're using pull DP and it depends on previous states only. Writing the prefixes logic was a bit cursed too. Also note the solution had some different state management like using inclusion exclusion and their DP was placing one element at a time I didn't super understand it. Also my DP we can avoid the prefix altogether since it's kind of a sliding window DP so there's a way to just make O(1) transitions where we drop out the element on the left end of the window.
Drill Type:
Implementshould implement bottom up pull DP
Solutions:
3865. Reverse K Subarrays
Problem Summary:
You are given an integer array nums of length n and an integer k. You must partition the array into k contiguous subarrays of equal length and reverse each subarray.
Notes:
Literally just loop and reverse
Solutions:
1787. Make the XOR of All Segments Equal to Zero
Problem Summary:
We have N <= 2000 numbers. arr[i] < 2^10. We can change a number in an operation. Find the min # of operations to make every window of size K have an XOR of 0.
Notes:
Observe the array needs to be periodic on size K. Split the array out into groups, so all indices i%k get put into the same group. All elements in a group need to be the same. We can dp(indexUpToK, prevXor) and loop on all 1024 new values to set for the new group but this is n * 1024 * 1024. Instead, observe that for a group we can either set all elements equal to an element in that group, or not in that group. If we choose the new total XOR including this group to be any of the 1024 values, we take the previous best DP and just pay the cost to change every element in the group to some new value that forces this new DP. That would be if we set all elements to a value not in the group. But if we set all elements to a value in the group, we CAN actually loop over those elements and all previous XOR combos. It looks cubic but it amortizes.
Drill Type:
Mindsolvere-read notes / code
Solutions:
1131. Maximum of Absolute Value Expression
Problem Summary:
We have two arrays of length N <= 4e4 with numbers <= 1e6. Find the max of |arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|
Notes:
First think about just the answer for 1 array. We can iterate on our j as the right number. If we assume the j-th number is larger we want to subtract the smallest i-th number. But i-th numbers have differing penalties. Like i=2 is better than i=3, assuming the values are the same, since mbej-i is larger. So we kind of do this lop off method of sorts and we track the previous smallest arr1[i] factoring in the penalty. But now for two arrays we need to do these things at the same time. We can run the procedure on both arrays at the same time assuming the j-th number is bigger for both arrays than their i-th numbers. If the j-th number is smaller we can re-run the procedure on the reversed arrays. Or we can just run it on both arrays where each element is multiplied by -1. What if the j-th number should be the smaller one in arr1 but bigger in arr2? Well we could multiply all elements in arr1 by -1. So Now if we assume the j-th element is bigger, call that B, and the i-th element A, we are doing -1 * (B-A) which ends up being A-B. So in total there's 4 combinations. A bit wonky to think about in terms of making sure we don't violate the maximum possible amount for |X-Y| but it works out Another way is to think of it like dp(index, isIntervalOpen, wasArr1Subtracted, wasArr2Subtracted) which is 8N dp. Remember we are essentially claiming there are 4 situations: (x_i+y_i+i) - (x_j+y_j+j); (x_i-y_i+i) - (x_j-y_j+j) ; (-x_i+y_i+i) - (-x_j+y_j+j); (-x_i-y_i+i) - (-x_j-y_j+j) And the result is the maximum of these four situations. Thus we create the list as [x_i+y_i+i] and so on.
Drill Type:
Mindsolvere-read notes and code
Solutions:
3555. Smallest Subarray to Sort in Every Sliding Window
Problem Summary:
We have an array of length N <= 1000 with numbers <= 1e6. For each window of size K, we can sort some subarray once. Find the min length we need to sort, for each window, to make that window mono-increasing.
Notes:
O(n^2) two pointers + prefix + suffix Since n is small we can treat this as n-k separate subproblems. For a given subproblem, its going to be [sorted prefix] [some mess] [sorted suffix]. We use two pointers and iterate L as long as it is mono-increasing, and that number is <= suffixMin[L+1]. Repeat on right side. O(n log n) We can basically do the above but binary search for the longest prefix and suffix that is valid. We can use DP to precompute the longest mono-increasing subarrays starting at each index L. And a sparse table to query range min and maxes. O(n) I think it is some adaptation of the above but using a monotonic property or something. Not really sure.
Drill Type:
Mindsolvere-read notes
Solutions:
1345. Jump Game IV
Problem Summary:
We have a list of N <= 1e5 numbers. We start at index 0 and need to reach N-1. We can do these in one move: Jump to index+1 Jump to index-1 Jump to any index which has the same value as our current value Find min # of operations to reach the end
Notes:
Normal BFS too slow because we literate on adjacent number types too much. We only want to do this once. Just do a BFS on indices and the first time we encounter a number type, loop through it. After clear that num->indices mapping or just mark that number type as processed. I tried it in a bit more convoluted way at first with tracking seenIndices and seenNumbers but ran into a weird issue where say at index 10 we go left to index 9 and see a number 9. Then in the same BFS layer at index 2 we go right to index 3 and see a 9, we would skip it incorrectly assuming we could reach it in one operation from the factor that 9 was already in seenNumbers set from the earlier iteration in this BFS loop, which is flawed. I introduced a new visitedNumbersThisLevel set to handle this but ended up still needing to clear out the numToIndices list to prevent TLE, so I was just making things complicated
Drill Type:
Mindsolvere-read notes
Solutions:
1888. Minimum Number of Flips to Make the Binary String Alternating
Problem Summary:
Given a binary string of length N <= 1e5 we can do these: Operation 1: Remove the front number and put it on the back Operation 2: Flip a bit Find the min # of operation 2s we can use to make an alternating binary string
Notes:
O(n) god tier sliding window super instructive One concept is if we make a doubled string, s+s, and we slide with size N, we get all rotations of the original string. We want to quickly find the # of mismatches against both binary string options. If we peg each global index to a desired number, like index 0 we desire 0, and also try index 0 we desire 1, we can basically track both of these in real time with a fixed sliding window. I think this means as we slide the strings we consider are basically flipping. O(n) simulation with deque? I think we could do the above with a simulation but it might be more annoying, or counting the connected blocks like 000 11 0 11 0 I feel like there is something there. Not listing since I didn't verify a valid solution. O(n) prefix + suffix If n is even then it must be 1010... or 0101... Rotating this turns one into another, so we can just check min(startWith0, startWith1) against our input string If odd then we do some weird thing with prefix and suffix I didn't learn Prob other solutions too
Drill Type:
Mindsolvere-read notes
Solutions:
635. Design Log Storage System
Problem Summary:
We have timestamps like Year:Month:Day:Hour:Minute:Second for example 2017:01:01:23:59:59 Each timestamp is given with an ID in put(id, timestamp) - we are implementing this class We also need retrieve(startTime, endTime, granularity) where granularity can be day/month/year/minute/second and we need to return all IDs of timestamps in between that time range, but only to that granularity. So granularity = Year means if start timestamp was in 2017 then anything in 2017 to the ending year is valid.
Notes:
# of operations is small so we can brute force. Easiest way is to, for a given query, truncate the prefix based on the resolution, and compare it to all other inserted timestamps with the same truncation, and just do lexicographical comparison I'm sure more advanced stuff like putting the times in a sorted container and binary searching, or building some trie/tree to dfs on, would work too
Solutions:
2084. Drop Type 1 Orders for Customers With Type 0 Orders
Problem Summary:
Given a SQL table of orders, return: if a customer had any order of type 0, do not return any type 1 orders from that customer, otherwise return them all
Notes:
Build a CTE for all orders of type 0, now return all orders of type 0, and 1 if the customer is in that CTE
Solutions:
1805. Number of Different Integers in a String
Problem Summary:
We have a string of letters and numbers like a123bc34d8ef34 Remove all letters forming 123", "34", "8" How many unique numbers are there?
Notes:
Basic string / array manipulation
Solutions:
667. Beautiful Arrangement II
Problem Summary:
Given k < n <= 1e4, construct a permutation of 1...N with exact K distinct gaps between two adjacent numbers.
Notes:
We can think of the values as a range with two pointers: 1 2 3 4 5 6 7 8 9 10 ^ ^ r pointer l pointer If we place them in opposites [1, 10, 2, 9, 3, ...] we get gaps 9 8 7 6 5 ... When we reach k-1 gaps placed, then we place the consecutive change 4 5 6 7 8 which only has gaps of 1 My implementation was not so clean
Drill Type:
Mindsolvereally quick re-read
Solutions:
1866. Number of Ways to Rearrange Sticks With K Sticks Visible
Problem Summary:
We have N sticks all different heights. We want to arrange them such that K are visible from the left. How many ways can we do this? N, K <= 1000
Notes:
Going left to right doesn't work. If we go right to left, we can either place the biggest and it is visible or we place some non biggest stick.
Drill Type:
Mindsolvere-read solution, note this concept of thinking from different angles
Solutions:
1784. Check if Binary String Has at Most One Segment of Ones
Problem Summary:
Check if a binary string has at most one contiguous segment of 1s
Notes:
Just iterate and track if we have seen a 1 yet
Solutions:
597. Friend Requests I: Overall Acceptance Rate
Problem Summary:
Given SQL tables of friend requests and accepted requests, count the % accepted. There can be duplicates.
Notes:
ROUND was needed, COALESCE, NULLIF since denominator can be 0, and to get the count of distinct (a, b) we have to do this sort of thing: (SELECT COUNT(*) FROM (SELECT DISTINCT requester_id, accepter_id FROM RequestAccepted)) Also needed ::numeric to get float division
Solutions:
464. Can I Win
Problem Summary:
Given numbers 1 to MAX, MAX <= 20, we take turns picking these without replacement. First player to get above desiredSum (<= 200) wins. Can player 1 force a win?
Notes:
Dp bitmask + try all options, n * 2^n time. Note edge cases (desiredSum is 0, or sum(1...MAX) < desiredSum).
Solutions:
C. Simons and Posting Blogs
Problem Summary:
We have different groups of numbers like [1, 4, 2, 1] [3, 5]. The total # of numbers is <= 3000. We pick an ordering for all groups. Process each groups elements then, as they come in order, we place that number at the front of the line, or if already in line, excise it from its spot then place it at the beginning. We want the smallest lexicographical final result.
Notes:
First any duplicate element in a group is redundant since only the last operation will matter. Second we think in reverse, we want the smallest ending element. So we can sort these arrays by their reversed lexicographical orders. But after we pick the smallest ending say [3, 1] ends in a 1 which is good, we should remove the 1 and 3 from all other groups now since those other groups 1s and 3s basically no-op since they get selected before this final [3, 1] group.
Solutions:
B. Simons and Cakes for Success
Problem Summary:
We are given n <= 1e9. Find the smallest K such that N is a divisor of K^N
Notes:
For sure if we set K=N then N is a factor of N^N so that's an upper bound. We basically need to pick some K, such that if repeated N times, it would cover all the prime factors of N. So if N had a prime factor 2, appearing 3 times, we need a 2 as a prime factor of K. We don't need multiple copies since I think the # of times the prime can appear is always < N anyway. So we can use pollard rho to prime factorize then just return each prime multiplied together, or iterate through all primes <= rootN and then at most one larger prime remains.
Drill Type:
Mindsolvere-note that we can get the prime decomposition in rootN time with the observation that only one prime can be >= rootN
Solutions:
A. Simons and Making It Beautiful
Problem Summary:
Given a permutation of length N <= 500, an index is ugly if it is the max of that prefix. We can swap up to one set of two indices. Construct a result array with the minimum ugliness.
Notes:
The max element is always ugly. Swap that to the front.
Solutions:
2735. Collecting Chocolates
Problem Summary:
We have given an array of length N <= 1000, arr[i] <= 1e9, and x <= 1e9. To get a chocolate at index i it costs arr[i]. All chocolates are different types. In one operation we can change the ith type to (i + 1) mod n for everything. Find the minimum cost to get chocolates of every type.
Notes:
For a given index, we could take this index, or loop backwards costing more. This is O(n^2). O(n log n) - super instructive but also hard As shifts increase, the cost for shifting does, a linear line with positive slope. The total cost to acquire items goes down, but the rate at which it goes down, slows. Basically like the left half of a convex function. This is kind of unintuitive because you might think like [1, 50, 100] after one shift the 1 saves 49, but after a 2nd shift it saves another 99, so isn't that a big gain? But I think it's because after 1 shift the 100 transforms into a 50. Anyway if you add these two functions together, the linear line and the convex esque chart, we get a unimodal V like graph. As long as we can "gradient descent" safely we can do a ternary search sort of thing, compare f(m) to f(m+1) and descend. We can implement this with the normal l<=r binary search I use. Also I think others used a monoqueue or something for the min cost in a range but I used sparse table. Also note the nice double array trick nums2 = nums + nums There is some O(n) I did not try to understand it. stack + calculus? https://leetcode.com/problems/collecting-chocolates/solutions/3651340/javacpython-stack-and-calculous-on-by-le-wtz6/
Drill Type:
Mindsolveread notes/code, just to be vaguely aware of the possibility a cost function might be unimodal, also reminder of the ternary search implementation, maybe look into the way I did it but also the 1/3 and 2/3 ternary search method?
Solutions:
2733. Neither Minimum nor Maximum
Problem Summary:
Find any number that is not the min or max in a distinct array
Notes:
Just look at the first 3 numbers
Solutions:
2710. Remove Trailing Zeros From a String
Problem Summary:
Given a number remove trailing 0s
Notes:
Just loop backwards
Solutions:
2679. Sum in a Matrix
Problem Summary:
Given a 2D matrix, repeat this: Pick the largest element from each row, delete it. Score the smallest of all of those. What is your final score?
Notes:
Sort each row, we get the max for each column at a time.
Solutions:
2678. Number of Senior Citizens
Problem Summary:
basic string parsing
Solutions:
2824. Count Pairs Whose Sum is Less than Target
Problem Summary:
Find the # of pairs with i<j and sum < target
Notes:
Brute force. For bigger constraints we could use an ordered set or seg tree or something silly
Solutions:
2817. Minimum Absolute Difference Between Elements With Constraint
Problem Summary:
We have an array of size N <= 1e5 with numbers <= 1e9. X <= N. Find the minimum absolute difference between two numbers that are spaced by at least X indices.
Notes:
We can maintain one ordered container which is like the left region of our array. As we scan right we add elements on the left to the sorted container, provided they are at least X away. Then we search for the closest number to our number at index i. We don't need to look right due to symmetry. Prob some other silly stuff like segment trees too can work in the way ordered sets do. Also since we don't need order statistics like kth smallest we can literally use a C++ set.
Drill Type:
Mindsolvere-read notes
Solutions:
2798. Number of Employees Who Met the Target
Problem Summary:
literally one of the easiest questions, just count the # of numbers >= X
Notes:
easy!
Solutions:
2788. Split Strings by Separator
Problem Summary:
Split each word in an array by a separator, basic string manipulation
Notes:
Basic string manipulation
Solutions:
2785. Sort Vowels in a String
Problem Summary:
Sort a string, consonants remain, vowels are sorted
Notes:
Just track them separately, sort, and use a counter on the vowels
Solutions:
3136. Valid Word
Problem Summary:
basically a string validation question, does this string fit these constraints
Notes:
just do what it says
Solutions:
3005. Count Elements With Maximum Frequency
Problem Summary:
Find the # of elements with a max frequency
Notes:
frequency map
Solutions:
2964. Number of Divisible Triplet Sums
Problem Summary:
Find the # of unordered triplets where the sum of numbers % d == 0. N <= 1000. arr[i] <= 1e9. d <= 1e9
Notes:
Enumerate pairs and then check in the suffix with a hashmap, O(n^2), I had a nice implementation where I pre-counted all numbers % d and subtracted the two i and j numbers if needed
Solutions:
2843. Count Symmetric Integers
Problem Summary:
Count hte # of "symmetric" numbers from low...high (small constraints). It is symmetric if the sum of the first half is the sum of the second half
Notes:
naive, iterate and count digit dp version: maybe dp(i, currSum, tight) and we subtract in second half, probably other variants
Solutions:
1758. Minimum Changes To Make Alternating Binary String
Problem Summary:
We have a binary string, we can toggle bits in an operation, find min # of operations to get the string alternating
Notes:
We can track misplaced numbers, so basically answer in one pass for both possible string outcomes
Solutions:
1130. Minimum Cost Tree From Leaf Values
Problem Summary:
Given an array of numbers. N <= 40, arr[i] <= 15, this array represents the inorder traversal of the leaf nodes of a binary tree (basically left to right ordering). Non-leaf nodes are the product of the largest leaf nodes in their left and right subtrees. Find the minimum sum of all non-leaf nodes.
Notes:
Solution 1: Observe we have some root node and will split the array into two subproblems at some partition point. So we have dp(l, r) with a for loop inside. O(n^3) time. Solution 2: Also observe that we can only pair two adjacent numbers together, forming a triplet, like: [4, 2] could become: 8 /. \ 4. 2 This now becomes one "unit" with a new max of 4 (as we take leaves), for all parents. So the 2 gets "eliminated" Every number will get eliminated at some point except the max. So we must eliminate the smallest number, might as well eliminate it now with its smallest neighbor, as we can never get a smaller neighbor since things monotonically increase. This could be done in O(n^2) or O(n) Kind of confusing
Drill Type:
Mindsolvere-read notes
Solutions:
3860. Unique Email Groups
Problem Summary:
Convert emails into normalized emails (string parsing), count how many there are
Notes:
just normalize and add to set
Solutions:
Border Subgrid Count II
Problem Summary:
Given an NxN (N<=500) grid of K<=26 letters, find the # of rectangular submatrices where the border is all the same letter. Report the # for each letter type.
Notes:
Enumerate (r1, r2) as top and bottom edges. For each of those, do a sliding window to the right. Maintaining the # of connecting chains down (precomputed with dp). Some bookkeeping if the chain types switch and whatnot This is O(n^3)
Drill Type:
Mindsolvere-read notes / code
Solutions:
All Letter Subgrid Count II
Problem Summary:
Given an NxN (N<=500) grid of up to K<=26 letters, count the # of sub matrices that contain each letter
Notes:
O(n^3 logn) should TLE: For each top left corner as (r, c), scan for the top right corner, this is n^3, then binary search for the heights and use a 2d sparse table to query a bitmask O(n^3) AC: For each (r1, r2) do a sliding window to count the # of rectangles with that top and bottom edge, kind of a weird sliding window with while l < n. Also used 2d sparse table to slide.
Drill Type:
Mindsolvere-read notes, acknowledge the perils of the 2d sparse table too, probably glance over code
Solutions:
All Letter Subgrid Count I
Problem Summary:
Given an NxN (N <= 3000) grid of up to K <= 26 letters, count how many square regions contain every letter.
Notes:
Naive O(n^2 log n * 26) - will TLE: For each (r, c) treat it as a bottom right cell, binary search on the answer for that, use 26 prefix sums to validate O(n^2 log n) 2d sparse table - I got TLE: For each (r, c) treat it as the bottom right cell, binary search, but use a 2d sparse table to check the bitwise OR of the region. Since it is square queries, our sparse table is n^2 log n build time. The K is not a factor here since it is bitmasks up to 1<<26 only. EDIT: Knattii from discord seemed to have gotten this AC with gemini optimizing it, not sure if it's using binary search or some weird variant: https://cses.fi/paste/0028da62634bea56fad1ed/ O(n^2k) - tle. with n^2 memory, triple for loop dp (each cell stores the shortest side length we need, to contain a letter, for all letters). This TLEd. See Solution 2 in code. O(n^2k) - passed. with nk memory, barely passed after lots of optimization with help from benq. Reorder the triple loop to process each row one at a time, for each letter, so we only need to store nk memory for the previous row. See solution 1. O(26n^2) Larry's idea (prob should tle), enumerate major diagonals, do a like 2d sliding window tracking the smallest square we need to get every letter. Can use 26 prefix sums to update. Or the same 2d sparse table to just query in O(1) instead of a sliding window transition. Maybe we can use the 2-stack trick for sliding window of bitwise OR to allow us to slide in O(1)? Or some crazy monoqueue idea.
Drill Type:
Implementre-read notes, probably implement 2d sparse table (even though it will tle) and the working solution that benq showed
Solutions:
Filled Subgrid Count II
Problem Summary:
We have an NxN (N <= 3000) square of up to 26 letters. Find the # of rectangle submatrices with all the same letter.
Notes:
O(n^2) with dp + histogram Build the "up-chains". Now we want to solve each histogram row in O(width). Normal count submatrices with all ones: For a row, we are treating the base of the rectangle on this row. For a given up-chain, we could take any of those heights up. We find how far left and right we can go based on two stacks (can probably do in one stack). To not double count horizontally, we make one direction <= and the other direction <. See code for more clarity. Double-counting vertically does not happen because we consider each row as a base layer, separately. But how do we not miss things? Say our up-chain is height 3. We find the cut-off for the left and right edges from our stacks. This counts rectangles of height 1, 2, and 3, up to those cutoffs, but rectangles of size 2 or 1 could go even further than the cutoff for 3. The implication is that those would be counted from another column in our histogram, where a lower height is considered the upper threshold. Not the most clear. Except to handle all the same letter, we pop from the stack while the letter is the same too. This is true O(n^2) Think we can do 1 stack maybe, I did 2. Largest rectangle in histogram has notes on the 1-stack variant, maybe applies here O(26n^2): Just do count submatrices of all ones, but run it once for each letter type. Might TLE thats 26 * 9e6
Drill Type:
Implementdef re-read notes and resolve
Solutions:
Filled Subgrid Count I
Problem Summary:
Given an NxN (N <= 3000) grid of letters, find the # of square subgrids that comprise the same letter.
Notes:
O(n^2) dp Square is easy because we can use the dp[r-1][c], dp[r][c-1], dp[r-1][c-1] strategy, and just check the letters match. This is O(n^2) O(26n^2 * n^2 logn) We could also binary search for the biggest square, for each cell as a bottom right corner, validating all letters are the same with a 26n^2 2d prefix sum. (Not sure if this passes in time) Don't think we can count square submatrices with monostack + dp, I think, since things get double counted. But we can find the largest, see 221: Maximal Square. We can also count the # of rectangle submatrices with monostack + dp (see 1504. Count Submatrices With All Ones)
Solutions:
84. Largest Rectangle in Histogram
Problem Summary:
Given an array of heights, find the largest area rectangle
Notes:
Each bar could be a bottleneck height, so find the largest rectangle we can make with that as the bottleneck. We need to know the first left smaller and first right smaller for each index. Can use two monostacks. Could do it with one stack: When you pop a bar, you already know both sides at that moment: pythonstack = [-1] # sentinel for c in range(w + 1): h = heights[c] if c < w else -1 # sentinel flush while stack[-1] != -1 and heights[stack[-1]] >= h: popped = stack.pop() # Right boundary: c (the thing that caused the pop) # Left boundary: stack[-1] (what's left after popping) width = c - stack[-1] - 1 res = max(res, width * heights[popped]) stack.append(c) The popped bar couldn't extend right past c (shorter bar blocks it). It couldn't extend left past stack[-1] (that's the first shorter bar to its left that survived). Both boundaries are known at pop time — no second pass needed.
Drill Type:
Implementsolve with 2 stacks, maybe read notes on one stack to get the logic
Solutions:
1504. Count Submatrices With All Ones
Problem Summary:
Given an MxN (M,N <= 300) binary matrix, find the # of submatrices of all 1s
Notes:
O(n^3) basic dp: Build the "up-chains" for each cell, now enumerate over each cell as a bottom left corner, scan right and update the count O(n^2) dp + stack Build the up-chains. Now we want to solve each histogram row in O(width). For a row, we are treating the base of the rectangle on this row. For a given up-chain, we could take any of those heights up. We find how far left and right we can go based on two stacks (can probably do in one stack). To not double count horizontally, we make one direction <= and the other direction <. See code for more clarity. Double-counting vertically does not happen because we consider each row as a base layer, separately. But how do we not miss things? Say our up-chain is height 3. We find the cut-off for the left and right edges from our stacks. This counts rectangles of height 1, 2, and 3, up to those cutoffs, but rectangles of size 2 or 1 could go even further than the cutoff for 3. The implication is that those would be counted from another column in our histogram, where a lower height is considered the upper threshold. Not the most clear. Think we can do 1 stack? I did 2. Largest rectangle in histogram has more on the 1-stack variant, maybe applies here
Drill Type:
Implementdefinitely need to review notes and re-implement for the n*m, it's hard
Solutions:
85. Maximal Rectangle
Problem Summary:
Given an MxN (M,N <= 300) binary matrix, find the largest area rectangle of all 1s
Notes:
O(n^3), build "down-chains" for each cell to see how far down we can go with all 1s. Now for each cell as the top left corner, scan right tracking the bottleneck depth. O(n^2) stack + dp Generate the up-chain of 1s for each cell. Now for each row we basically get a histogram. We will attempt to get the max square in this row in O(rowLength) time. A given up-chain can go left and right as long as those ranges have >= up-chains. So we find the first left smaller occurrence and first right smaller occurrence with two stacks, and update the result. Since we try every possible up-chain this works. We can also use one stack where when we pop something we update the popped bar's right edge, and as we pop things we update the poppers left edge, but this is confusing lol. Note that we cannot count rectangles with this, I think, since some things get double counted. Note that we cannot find the max rectangle using the O(n^2) pure dp from max square, because dp[r-1][c] dp[r-1][c-1] dp[r][c-1] doesn't hold properly for rectangles. We also cannot binary search. There is some sort of n*m dp though, it's in the LC editorial. I didn't try to understand it, claude posted this summary: It's tracking three arrays as it scans row by row: height[j] = consecutive 1s going up (same as histogram) left[j] = leftmost column this height can extend to right[j] = rightmost column this height can extend to (exclusive)
Drill Type:
Implementre-read notes, contextualize with the other rectangle dp questions
Solutions:
221. Maximal Square
Problem Summary:
Given an M <= 300 x N <= 300 binary matrix, return the max size submatrix of all 1s
Notes:
O(n^3): For each cell compute the longest "down chain" of 1s. Now iterate on each top left cell, for each of those loop right on the columns and check the down-streak bottleneck. O(n^2 log n): For each cell as a bottom right, binary search on the largest square, we can compute if a square is valid in O(1) with a 2d prefix sum query O(n^2): For each cell as the bottom right, the largest square is basically 1 + min(dp[r-1][c], dp[r-1][c-1], dp[r][c-1]) O(n^2) stack + dp: Generate the up-chain of 1s for each cell. Now for each row we basically get a histogram. We will attempt to get the max square in this row in O(rowLength) time. A given up-chain can go left and right as long as those ranges have >= up-chains. So we find the first left smaller occurrence and first right smaller occurrence with two stacks, and update the result. Since we try every possible up-chain this works. We can also use one stack where when we pop something we update the popped bar's right edge, and as we pop things we update the poppers left edge, but this is confusing lol. Note that we cannot count squares with this, I think, since some things get double counted.
Drill Type:
Implementre-read notes, probably implement the n^2 dp and the n^2 dp + monostack
Solutions:
1277. Count Square Submatrices with All Ones
Problem Summary:
Given an M <= 300 x N <= 300 binary matrix, return how many square submatrices are all 1s
Notes:
O(n^3): For each cell compute the longest "down chain" of 1s. Now iterate on each top left cell, for each of those loop right on the columns and check the down-streak bottleneck. O(n^2 log n): For each cell as a bottom right, binary search on the largest square, we can compute if a square is valid in O(1) with a 2d prefix sum query O(n^2): For each cell as the bottom right, the largest square is basically 1 + min(dp[r-1][c], dp[r-1][c-1], dp[r][c-1]) Don't think we can count square submatrices with monostack + dp, I think, since things get double counted. But we can find the largest, see 221: Maximal Square. We can also count the # of rectangle submatrices with monostack + dp (see 1504. Count Submatrices With All Ones)
Drill Type:
Mindsolvere-read notes
Solutions:
2144. Minimum Cost of Buying Candies With Discount
Problem Summary:
We have N candies with different costs. If we buy two of cost X and Y, we can get a third of cost Z for free, provided Z <= min(X, Y). Min cost to get all candies?
Notes:
Sort, iterate backwards, every 3rd is free.
Solutions:
356. Line Reflection
Problem Summary:
Given N points on a plane, find if there is a vertical line that can reflect the points around it. Duplicate points can exist but we don't need the counts to match up. For instance [-1, 0] [-1, 0] [1, 0] is valid around the x=0 line
Notes:
Find leftmost and rightmost X to infer what must be the reflection line X, for each point, ensure at least one reflect point exists, O(n)
Solutions:
742. Closest Leaf in a Binary Tree
Problem Summary:
We are given a binary tree and a specific node K, find the closest leaf node to it (either above or below)
Notes:
-Convert to graph and BFS -Think reroot dp in theory could be done which is just silly, but we could do it for all nodes I'm guessing -Precompute closest distance for each node in that subtree, memoize. Now loop over all ancestors of K, finding their closest in their subtree, updating answer
Solutions:
2271. Maximum White Tiles Covered by a Carpet
Problem Summary:
We have N tiles like [1, 5] [10, 11] that are disjoint. Tiles can go up to 1e9. We have a carpet of length up to 1e9. Find the max # of tiles we can cover.
Notes:
Claim: An optimal answer can always be formed by placing a carpet that starts at the beginning of a tile (or ends at the end of one). Since sliding by one would always decrease the answer by one, and at most increase it by one. This makes implementation a bit easier, used prefix sums and handled some edge cases could use binary search too to find end points
Drill Type:
Implementshould re-implement this
Solutions:
A. Guards
Problem Summary:
We have N <= 8000 prisoners in an array. And G <= 3000 guards. A guard can watch over a subarray. Each prisoner has S_i intelligence. If a guard is watching k people, each prisoner has k*S_i chance to escape. We need to partition the N prisoners into G groups of guards with a minimum total escape score.
Notes:
Naive dp is: dp(i, guardsPlaced) for i in range(n)... The i, opt(i) pattern feels monotonic, intuitively have guards "balanced out" is better (quadrangle inequality) so we use dnc dp, O(G * N log N): for guards in range(2, G + 1): // execute the solve here Also our cost function is convex, the more guards we add, the lower the total escape chance, but smaller reductions each time, could alien trick for N G log max
Solutions:
3500. Minimum Cost to Divide Array Into Subarrays
Problem Summary:
We have two arrays nums and cost of length <= 1000, and K <= 1000. We can divide nums into any amount of partitions. The cost of the i-th subarray (1-indexed), ending at index r, is: (sum(0...r) + (i*k)) * sum(costs from l to r) Find the minimum cost
Notes:
O(nk log n) DNC DP: So this question kind of reads like DNC dp in that we partition it, but I have no proof that the i, opt(i) is monotonic, or maybe this dnc dp works without that? It's also weird because we aren't given a fixed K But anyway I tried it. The difference is instead of a cost(i, j) we need cost(i, j, subArrayNumber). O(n log n) CHT Now for our dnc dp we loop up to N partitions and do our standard strategy. It AC'd in C++. Could optimize to use 1d space. This also uses CHT and someone did an amazing write-up here: https://leetcode.com/discuss/post/6618678/convex-hull-trick-li-chao-tree-notes-by-l4jyd/ Maybe li-chao tree is useful too. CHT can get N log N. O(n^2) DP with a clever observation There is some math which I will paste in from claude here, I didn't learn or understand this: Ah I see. The math trick eliminates the partition index p, which is the key step. Let me explain: The original cost for partition p covering arr[l..r] is: (A[0..r] + k*p) * C[l..r] That p term is nasty — it depends on which partition number this is. But expand it: A[0..r] * C[l..r] + k * p * C[l..r] Now sum over all partitions. The k * p * C[l..r] part becomes: k * (1*C[i1..j1] + 2*C[i2..j2] + 3*C[i3..j3] + ...) But partition p has C[ip..jp], and partitions p+1, p+2, ... also exist. So the coefficient p on C[ip..jp] is equivalent to saying: "C[ip..jp] gets counted once for itself, plus once for every partition from 1 to p." Which is the same as: every element's cost gets counted once for every partition that comes at or after it. That simplifies to: k * C[i..end] for each partition starting at i The p disappears. Now the DP is: dp[i] = min over j of: A[0..j] * C[i..j] + k * C[i..end] + dp[j+1] And A[0..j] * C[i..j] expands to prefA[j+1] * (prefC[j+1] - prefC[i]) which is prefA[j+1] * prefC[j+1] - prefA[j+1] * prefC[i]. That's the form m*x + b where m = -prefA[j+1] and x = prefC[i]. That's where CHT comes in — you're minimizing over lines. Opus 4.6
Drill Type:
Mindsolvere-read notes, mostly care about dnc at this point in time
Solutions:
1536. Minimum Swaps to Arrange a Binary Grid
Problem Summary:
We have an N x N (N <= 200) binary grid. We need to swap adjacent rows and make it so all cells above the major diagonal are 0s. Min # of swaps, or -1 if doable. See picture in the problem to understand better.
Notes:
1/ Remap each row to the largest contiguous 0s suffix 2/ For each row we have a threshold where we can only afford some suffix of X or higher 3/ We can greedily scan for the first next row after this and simulate the swaps. It looks n^3 but the swap only runs once per row so it is n^2 Can we do better, assuming the input was given to us in an O(n) format instead of O(n^2)? Well we need to support a range query "earliest >= X" and a cut and paste. I think a treap can do it but not sure. Maybe some other structures like some seg tree where we denote "used" rows
Drill Type:
Mindsolvere-read notes, glance at code if confused about the n^2 vs n^3
Solutions:
E. Partition Game
Problem Summary:
We have an array of N <= 35,000 numbers and a K <= min(N, 100). We need to partition the array into K sections. The cost of a section is the sum of last-first occurrences of each number in that section, e.g. a section [0, 1, 2, 3, 0, 6, 1] would have cost 4+5 (distances of first and last 0, first and last 1). Find the min total cost.
Notes:
Gives quadrangle inequality vibes, we want things to be "balanced" / i, opt(i) is monotonically increasing, so we can try DNC DP Obviously naive DP is dp(i, k) for i in range(n)... which is n^2 k way too big. DNC DP O(k n log n): We seed the DP which is easy, cost of partitioning 0...i for all i, into 1 partition. Now loop on partitions, for each partition, do solve(fillL, fillR, leftJ, rightJ) But it is not easy to get cost(l, r) in O(1) and we cannot precompute a cost table. Instead we could use the magic mo's trick + dnc dp. I tried simulating with deques for each number type, like number -> deque of indices, to get the total sum of the window, but it was too slow I believe constant factor. Refactoring to just use an array where we precomputed nxt[i] and prv[i] so we can support addR remR addL remL worked. This makes k n log n time. SEG TREE DP O(k n log n). Make a dp which represents the cost of partitioning 0...i initially into 1 partition. Now loop on partition count. For a new partition count say 2, build a lazy seg tree on the old dp, in O(n) time. This seg tree, like seg.queryPoint(i), will represent the total cost of dp[0...i] + cost(i + 1, j), as we loop on j. Honestly should read the code for this, but basically we can do range add when we introduce a new number in the j for loop. And then use a range query to update ndp, and then swap them. Also ran into some annoying overflow issues, just used LLONG_MAX/4 everywhere which helped.
Drill Type:
Implementmaybe implement both seg tree dp and dnc dp with mo's
Solutions:
B. The Bakery
Problem Summary:
We have N <= 35000 cakes and need to put them into K <= min(50, N) boxes (basically partition the array). The cost of a box is the # of unique elements in it. Find the min cost.
Notes:
Alien trick doesn't work I believe since N is large. Natural dp is dp(i, k) for i in range(n)... DNC dp can be done in a few ways: 1) We need cost(l, r), we can get # unique in a range with persistent segment tree in logN, and there are n log n recursive calls to solve, so that's like n log^2 n work. So O(k * n log^2 n) overall. 2) We can use the mo's trick which I think somehow makes it just O(k n log n) 3) There is some other editorial using a lazy segment tree + dp, I believe it is like Codeforces: Partition Game which I have notes for
Drill Type:
Mindsolvere-reading notes for all dnc dp questions
Solutions:
Houses and Schools
Problem Summary:
We have N <= 3000 houses and need to establish K <= N schools. Each house has <= 1e9 people at its position. After placing the houses each student will walk to the closest school. Find the min total distance.
Notes:
DNC DP: O(n^2 + k n log n) So observe we can think of this as partitioning the array into K groups and for each group pick a spot everyone walks to. If we optimize this, it actually optimizes the overall question. Then we just need a cost[l][r] function and we can use DNC dp. We could precompute this with a nested for loop and tracking the median weights, my code has a clean version that I saw. Then just DNC DP. Note that the mo's trick (which I don't fully understand) I'm not sure if it is doable with weighted medians so I don't know if we can drop the n^2 precomputed cost table complexity ALIEN TRICK: O(n^2 log max) Since as we add more schools, the total walking drops, but by less and less, the function is convex. I did not implement this.
Drill Type:
Mindsolvere-read notes, doing for all dnc / alien trick
Solutions:
E. Ciel and Gondolas
Problem Summary:
We have N <= 4000 people and K <= min(800, N) gondolas. Partition the people into K gondolas. Each set of people (i, j) has an unfamiliarity score <= 9. A gondola unfamiliarity is the sum of all pairs of those scores. Find the min unfamiliar score.
Notes:
ALIEN TRICK n^2 log max This gives concave/convex f(x) vibes, as we provide more gondolas, the score drops, but by less and less. So we can alien trick. Required some optimizations in C++ to pass in time. Binary search on the lambda (y), and for each iteration run a naive n^2 dp. For the binary search logic // min or max # of partitions in the dp logic, there's notes in a different question somewhere This is n^2 log max DNC dp n^2 + k n log n Since the i, opt(i) is monotonic (quadrangle inequality esque logic, we want to "spread things evenly") we can use DNC. We can precompute cost[l][r] for all pairs and just access that in the table. Note that if we tried the mo's trick (which I don't fully understand) we might need n^2 prefix sums precomputed, and the IO is n^2 anyway, so doesn't help Don't really understand if CHT/li-chao apply or not, claude claims no
Drill Type:
Mindsolveput mindsolve to re-read notes because probably should re-read all alien trick / dnc dp questions
Solutions:
1307. Verbal Arithmetic Puzzle
Problem Summary:
We have up to 5 words and a result word, up to length 7, like: words = [SEND, MORE] result = MONEY See if we can assign an injection of the letters -> some digit (no digit is repeated) to make the sum of the words equal the result.
Notes:
Naively we could try all 10! options but it is too slow. Even if we generate the nPk choices a bit more quickly it is still too slow, worst case is up to 10 unique letters anyway so that would require 10! The trick is to prune our backtracking, imagine this: # SEND # MORE # MONEY We start from the right column and validate the sums add up correctly with our mapping, it it fails we terminate early. Also we add result to one of the words, but subtract for that case, makes the backtracking logic easier, so we don't have to finish backtracking on just the input words then try to come up with a remaining mapping for letters in result, that weren't yet mapped. So I did backtrack(row, col, carryAndSum). Starting col=0 means the rightmost edge. Once we hit row=numWords we go left one column and up to the top. The important aspect is the carry logic: # if we ran out of words, as long as we have a carry that is divisible by the next digit we are good # for instance 30+40 (so basically 3+4) is 7 but if we carry a 7 we can never neutralize that since all future numbers operate on a larger magnitude # but 3+4+3 = 100 basically and that can be neutralized if carryAndSum % 10 == 0: return backtrack(0, col + 1, carryAndSum // 10) return False A lot of other edge cases in this too, would re-read code Also note the cool c = w[~col] trick to get a backwards index
Drill Type:
Implementeither re-read code at least + notes, or implement
Solutions:
F. Yet Another Minimization Problem
Problem Summary:
We have an array of N <= 1e5 numbers <= 1e5, and K <= min(N, 20). Divide the array into K partitions with minimum total cost. The cost of a partition is the # of unordered pairs of the same elements.
Notes:
Note a naive DP (i, k) for j in range(n)... which is O(n^2 k). Also note we cannot precompute costs for all subarrays since n is too big. We use DNC dp. The cost function is monotonic as we allow more partitions the total cost drops, but by less and less. The issue is we need to loop for leftJ to min(mid, rightJ) (or maybe always mid works, I'm not sure yet as per notes in cses subarray squares). I tried looping backwards from mid to leftJ and maintaining an unordered map for each recursive call, but it TLEd. Instead, I was able to solve it by looping from leftJ to min(mid, rightJ) but we cannot make a new frequency map each time then, because we would need to start looping from mid, going left, to fill it out accurately, but we are forced to loop from min(mid, rightJ). To solve this I used a single global frequency map and did the queries mo's algorithm style, I don't quite understand how the natural recursion order of dnc dp works for this but it did. Note that we I don't think we can use alien trick for this as that is n^2 log max There might be some more cursed methods like dnc dp + alien trick(??? according to claude) or other techniques but I'm not very familiar
Drill Type:
Implementre-read notes, maybe re-imeplement
Solutions:
631. Design Excel Sum Formula
Problem Summary:
We have an excel sheet of at most size 26x26. Support these things: -Set a cell to an int value -Set it to a list of things like [A1, A2:B4, C2] which means it is the sum of all those regions and cells -Get the value of a cell
Notes:
Write heavy: O(1) to set, then we recurse in the cell. IMPORTANT, since we have a dag we can have exponential complexity by re-computing the same sums. Like A1=B1+C1 and C1 = B1 + B2 we recompute B1 twice. So we can be clever and modify the get signature to get(row, col, memo=None) and re-use a memo cache across recursive calls. This makes it so our get in the worst case solves each cell once, otherwise it just loops over every cell Read heavy: Like extend style, store the deps maps and make get O(1), maybe some nice topo sort implementation -Could also jankily re-compute everything after each write but that isn't good
Drill Type:
Implementpotentially implement the read heavy version, also re-read notes for passing memo=memo that was clean
Solutions:
1689. Partitioning Into Minimum Number Of Deci-Binary Numbers
Problem Summary:
A number is deci-binary if it has only 1s and 0s with no leading 0s, like 101 or 1100. Given a number of length <= 1e5, find the min # of deci-binary numbers that add to n
Notes:
It is just the max digit, we could probably easily prove such a construction exists
Solutions:
3826. Minimum Partition Score
Problem Summary:
We have an array of size N <= 1000 and a k <= N. Partition the array into K subarrays with a min sum score. The score of a subarray is sum * (sum+1) / 2 Arr[i] <= 1e4
Notes:
Naive dp(i, subarraysMade) for j in range(i, n) is O(n^2 * k) We can use dnc dp, dp[i] = the answer for making partitions in 0...i as we loop on partitions Then inside the loop we check the midpoint and do the solve(fillL, fillR, leftJ, rightJ) thing which does n work per layer with logN layers so n log n * k We can also do alien trick: The cost function as a function of the # of partitions used is like this __ / | (concave) More partitions lets us reduce the cost to the individual elements As we drop the penalty we get optimal dp answers with more subarrays being used, ideally we get exactly K naturally use GOLDEN RULE from cses subarray squares Probably li-chao tree, cht, alien trick + cht can be used
Drill Type:
Implementpractice solving this, re-read notes, maybe the other dnc dp questions too
Solutions:
Subarray Squares
Problem Summary:
Given N <= 3000 numbers, A[i] <= 1e5, and K <= N, divide the array into K partitions to minimize the sum of squares of sections. So |1 3 | 4 | 2 1 | = 4^2 + 4^2 + 3^2
Notes:
Alright so there is many ways to solve this: First a naive dp(i, subarraysMade) and we loop on the next subarray. This is n^2k. DNC DP: Observe if we write out the starting indices for some index i, and the optimal ending index opt(i) opt(1) = 0 opt(2) = 1 opt(3) = 2 opt(4) = 2 ← stayed opt(5) = 3 opt(6) = 4 opt(7) = 4 ← stayed opt(i) monotonically increases More formally we can use the quadrangle inequality to show when DNC dp applies So we have dp[i] is the # of ways to partition 0...i, initially it is for 1 partition (entire array), and we loop on partitions: for p in range(2, k + 1): ... We could also have 2d dp[i][prevPartitions] but we only need the previous layer We need to fill out every index in the dp as we add a partition, consider the middle index. Brute force by enumerating all j <= i. So opt(j) = i Now any i' < i will have j' <= j and any i' > i will have j' >= j Recursive on the next cases. The format is dp(fillL, fillR, leftJ, rightJ). We recurse logN times and each layer does N work. So N log N * K Some other good Claude notes on dnc dp, the intuition for what monotonicity really means / why it works: Let me reframe it. Forget suffixes. Think about it concretely. You have an array and you're splitting it into exactly p partitions. You've already handled the first p-1 partitions. Now you need to decide where the last partition starts. array: [... ... ... | last partition] ^ j = start of last partition dp[mid] = best cost when the last partition ends at mid. You're finding the best j (where the last partition starts). Now compare two endpoints: mid = 5: best to start last partition at j = 3 [...|3,4,5] mid = 7: where should last partition start? [...|?,?,?,?,?,7] Could the optimal j for mid=7 be j=2, which is BEFORE j=3? Think about what that would mean. For mid=5, you said "starting at 3 is best — starting at 2 makes the last partition too big." But for mid=7, which has an even LONGER right side, you're saying "actually starting at 2 is better — I want an even bigger last partition." That's contradictory. If a wider last partition was bad for mid=5, it's even worse for mid=7 because you're adding more elements to an already-too-wide partition. The cost grows superlinearly (due to the product structure), so widening an already-wide partition hurts more than widening a narrow one. That's the monotonicity intuition. The optimal start point can only move right (or stay) as the endpoint moves right, because going left would mean making a bigger partition when a smaller one was already preferred. Also quadrangle inequality visual: This isn't saying "splitting is cheaper." It's saying: two overlapping intervals cost less than one big + one small. Visually: Overlapping (cheaper): [a-------c] [b-------d] Nested (more expensive): [a--------------d] [b---c] "Balanced" splits are cheaper than "unbalanced" splits. This is what guarantees monotonicity. If the optimal split for mid=5 is j=3, then for mid=7, going back to j=2 would create a more unbalanced split (tiny left, huge right), which QI says is worse than a more balanced one. So j can only move right. UNDERSTANDING THE ASYMPTOTICS OF DNC DP: It is important to understand the point of all the variables in solve(fillL, fillR, leftJ, rightJ) For starters, fillL and fillR simply mean this recursion function + all its children will fill out that range in the dp eventually, each call fills one occurrence. We recurse based on the midpoint of these, so when we recurse we split into two equal halves. This implies we have logN layers. But we must understand how much work is done in each layer. We want it to be N work. Remember each layer has this many nodes: 1, 2, 4, 8, ... where a node = a call to the solve function. If we did not track leftJ and rightJ, we could definitely just scan from 0...mid each time, but that is doing too much work. For instance imagine the bottom layer where solve is called on a single fillL=fillR, for each of those N cases we are doing work, like 1 for the leftmost call, 2 for the next one, all the way to N. This is 1+2+...+N which is already N^2 work in a single layer. With the J boundary we reduce the work. Imagine in our root call we do N work for the scan and assign some J, could be at i=0, i=mid, or anywhere in between. When we recurse it looks like this: root call: |________________mid_______________| ^optimal J next layer: |_______mid______| |_______mid_______| ^j In this second layer left child we know we should only go up to j, it cannot be on the right, since that midpoint is left of the earlier midpoint. So we do this much work: |_____| In the right child we must start at J and go right, doing this work: |_____________________________| This is N work I think it just scales, say left child is one third the length, it will spawn off two nodes to do one third and work total, and the right child would spawn off two-thirds and work total. As far as if we can loop from leftJ to mid or leftJ to min(mid, rightJ), or even leftJ to rightJ (which could be above mid, which fails correctness, but I'm talking about complexity here). I'm not actually sure this makes a difference in the asymptotics, but we definitely cannot start from 0 each time because of the last layer being 1+2+...+N work. As per codeforces "yet another minimization problem" I believe we need to go to min(mid, rightJ) just based on the test cases / design of the question there. ALIEN TRICK: Easy to follow with these graphs. /Users/ishaan/Desktop/alien1.png /Users/ishaan/Desktop/alien2.png Same images on reddit: https://www.reddit.com/user/leetgoat_dot_io/comments/1rhjv5f/lagrangian_relaxation_notes/ I understood it from here: https://usaco.guide/adv/lagrange?lang=cpp (will paste image text at the bottom too) Say we are solving given an array of numbers we want K disjoint subarrays to maximize the subarray sums. Naive is N*K basically dp(i, inSubarrayOrNot, subsMade). Get max subarray sums. Read the image text: task is to partition arr into k disjoint subarrays maximize the sum of elements in the subarrays k=1 we take the max subarray, k=2 the next max gets added it slows down, so f(x) is concave now introduce a penalty lambda, call it y, per subarray we want to maximize the score with this penalty with any # of subarrays we want to add subarrays as long as the incremental gain is > y our score is now f(x) - yx, call that v(x) call c(y) the rightmost x that maximizes v(x): the v(x) curve is concave, there is a flat part where the incremental gain equals y (could be multiple points) or if none, it is flat at the rightmost x where the slope of f(x) > y so to maximize v(x) we find the rightmost x with slope f(x)>y, this is c(y) higher y means bigger penalty and so fewer x is used, and vice versa say y=1e100 we only use one partition, but y=0 we use n partitions we binary search for some y which has a flat x = k bigger y would result in <= partitions smaller y would result in >= partitions ideally: we find a y where the DP naturally chooses k partitions annoying case: does not exist GOLDEN RULE: We could find the MAX number of partitions or the MIN number of partitions, it doesn't matter. If we find the max, we want to write the result in the binary search as long as partitions >= k, because it's possible the flat part goes left past k, if we find the min, we want to write the result as long as partitions <= k. Now how to apply the logic to this CSES question? Each additional subarray we allow decreases the score, but by less and less (intuition or quadrangle I guess) So we have a convex curve kind of like this: f(x): | \ \__ As we increase the partitions allowed, the min score goes down. We binary search on lambda (call it y) As y ^, optimal partitions goes down As y v, optimal partitions goes up It is possible no y gives exactly K partitions but that is okay. Define v(x) as f(x) - yx which looks like this. Too few partitions and we spend too much on the cost function, too many and we spend too much on the penalty Some sweet spot where the f(x) slope is worth the y penalty, like the slope is more sharply down than y | | \ / \____/ If we binary search on the smallest penalty where we have <= K partitions we find our answer like this. Imagine we used 3 partitions but want 5. We need to decrease y. Why didn't we use 4 and 5 partitions? Because y was too big compared to the benefit of those partitions. We could pay for them though (record our answer in the binary search here). And trust that as we decrease y we would use more partitions. But if we ever use > k partitions, as the least amount of partitions possible, then that is invalid. Memorization: Minimization: save when partitions ≤ k (too few) Maximization: save when partitions ≥ k (too many) The universal version is: save when the DP's partition count is on the side of k that's closer to the "free" extreme IGNORE^ use GOLDEN RULE above OTHER METHODS: li-chao tree? cht? alien trick + cht? alien trick + li-chao tree?
Drill Type:
Implementre-read notes, images, and implement alien trick and dnc
Solutions:
3666. Minimum Operations to Equalize Binary String
Problem Summary:
We have a binary string of length N <= 1e5. In an operation we flip K <= N bits. Find min # of operations to get all 1s, or -1 if impossible.
Notes:
Two methods: 1/ O(n log n) Observation 1, if k is even the parity never changes. We either flip an even amount of 0s and an even amount of 1s which cancel, or an odd amount of each. If k is odd the parity does change by the same logic. So if we are in a state with an odd amount of ones, we either transition to only even states, or only odd states, depending on k. The states are contiguous, like 4 ones could transition to (1, 3, 5) or maybe (2, 4, 6, 8) etc. If we split those into two, we can enumerate the contiguous range, pulling them out of 2 multisets so we don't repeat work. Basically a bfs. 2/ O(n) For a given amount of operations we want to see if we can distribute an odd number of operations to each 0, and an even number to each 1. This can be done with a few necessary and sufficient conditions as outlined here (Hall's theorem) https://leetcode.com/problems/minimum-operations-to-equalize-binary-string/solutions/7613102/o1-math-solution-full-proof-intuition-ex-mvvu/
Drill Type:
Mindsolvere-read notes, ideally think about why my dp for loop caching or some other math ideas don't work, one day
Solutions:
755. Pour Water
Problem Summary:
We have a heights map of width <= 100 and need to pour V <= 2000 droplets of water. We pour at index K. If a droplet would eventually be lower by moving left, it moves left. Otherwise, right. Otherwise, the droplet pours into K. Return the final output.
Notes:
Kind of hard to understand the droplets, basically we should scan left while mono-decreasing, noting every best index so far (only the strict height drops help), for instance in [1, 1, 2] if we start pouring at k=2 we should have [1, 2, 2] not [2, 1, 2] as per the rules of the question. Could implement this with scanning left while mono-decreasing, then right once more, or just track the best index. Repeat for right. If no spots, fill at k. This is v*n time. I tried segtree "leftmost index <= v" like that but it doesn't work because if there is a blocker in the way like [1, 5, 2] we cannot go from i=2 to i=0. But maybe if we modify our segtree to track the # of local inversions it could work? Also I tried some simpler two pointers idea but it doesn't work because I kind of misunderstood the behavior of the droplets. There is a V+N I should try to understand: https://leetcode.com/problems/pour-water/solutions/113003/cjavapython-ovn-time-solution-using-2-po-h8z6/
Drill Type:
Implementre-read notes and probably implement the v+n one day
Solutions:
538. Convert BST to Greater Tree
Problem Summary:
Given a BST, convert it to a greater sum tree, where every node stores the sums of all elements above it
Notes:
Same as question 1038 but leaving notes here: -Best way is reverse inorder traversal then keep track of running sum -I also included a jank solution dfs(node, sumFromAbove) but it is tricky, the way the sum from above works isn't as easy as it first seems -Can obviously store values in array and loop backwards, but that is just solution #1
Drill Type:
Mindsolvereview notes, mostly solution #1
Solutions:
1038. Binary Search Tree to Greater Sum Tree
Problem Summary:
Given a BST, return a greater sum tree, every node stores the sum of all elements greater than it.
Notes:
Same as question 538, see that for details
Solutions:
E. Pavel and Triangles
Problem Summary:
We have N <= 3e5 possible lengths of sticks. Each length is a given power of 2, so [2, 3, 1] means we have 2 sticks of size 2^0, 3 sticks of size 2^1, and 1 stick of size 2^2. Find the max # of non-degenerate triangles we can make.
Notes:
Note we can only make equilateral triangles and isosceles of (i, j, j) where i < j. Like 2, 8, 8. The greedy strategy is to enumerate j in order, pair a side length as much as possible with some previous i, so (i, j, j) and any leftover make triples. We can prove this with some complex casework to show that this can never not be optimal. I just guessed. To prove correctness, let's take our solution and one of the optimal solutions. Let's find the first difference in them if we consider the triples in the same order as our solutions considers them. There can be only one type of difference: we take some triple while the optimal solution skippes it. It can't be be the other way around because we always take a triple if there is one. So there are a few cases now: <casework here>
Drill Type:
Mindsolvere-read notes because the casework is so complex I just want to build intuition / reminder about trying different ideas
Solutions:
D. Wonderful Lightbulbs
Problem Summary:
We have a cartesian grid. Each point has a lightbulb. All are off except one. We choose an (x, y) and toggle the states of these bulbs: X XX X We do this an arbitrary amount of times and have a resulting set of bulbs that are on/off. Find a viable bulb that was initially lit.
Notes:
Invariant 1: The operation can never toggle the parity of a vertical line Invariant 2: The operation can never toggle the parity of a major diagonal line Use these two to locate an odd vertical line and odd major diagonal.
Solutions:
D. Prime Graph
Problem Summary:
We have N <= 1000. We need to make a graph: -Simple undirected graph (no dupe edges, no self-edges) -Exactly N vertices -Total # of edges must be prime -The degree of each node must be prime Construct the graph
Notes:
Start with a simple circle graph, every node has degree 2 which works. Now pair up two nodes to give them degree 3. Repeat until prime total # of edges. Expected # of operations is small due to prime gaps.
Solutions:
A. Ilya and a Colorful Walk
Problem Summary:
We have N <= 3e5 houses each with some color <= N. Find the max distance between two houses with differing colors.
Notes:
The answer must use one of the two endpoints, proof by contradiction
Solutions:
603. Consecutive Available Seats
Problem Summary:
Given a SQL table of seats in a cinema, find all empty seats that have an adjacent empty seat
Notes:
Selected a seat where the seat_id+1 or -1 in a subquery
Solutions:
1084. Sales Analysis III
Problem Summary:
Given a SQL table of products and sales find all products that were only sold in Q2 2019
Notes:
Join these two tables together and group by the product, HAVING a min and max sale date in range
Solutions:
2426. Number of Pairs Satisfying Inequality
Problem Summary:
We have two arrays of numbers N <= 1e5. Find the number of pairs (i, j) with i<j and nums1[i] - nums1[j] <= nums2[i] - nums2[j] + diff.
Notes:
Observe that: nums1[i] - nums1[j] <= nums2[i] - nums2[j] + diff Can be rewritten to nums1[i] - nums2[i] <= nums1[j] - nums2[j] + diff So we make a remapped array with the differences and get: arr2[x1] <= arr2[x2] + diff This is a standard sorted containers, seg tree, merge sort reverse pairs esque solution, etc
Drill Type:
Mindsolvere-read notes because I liked the math
Solutions:
1995. Count Special Quadruplets
Problem Summary:
Given an array of numbers N <= 50 find the # of quadruplets (a, b, c, d) such that nums[a] + nums[b] + nums[c] = nums[d]
Notes:
n^4 and n^3 are trivial but there is a beautiful n^2 Iterate over c backwards, and d after c. We track a map of (nums[d] - nums[c]) -> count for the right side. Fix the b-th element at c - 1. Now iterate over the a elements before b.
Drill Type:
Mindsolvere-read code for n^2
Solutions:
3851. Maximum Requests Without Violating the Limit
Problem Summary:
We have N <= 1e5 requests of the form [userId, time] <= 1e5. We are also given k <= n and window <= 1e5. A user violates the limit if they take more than k requests in a window [time, time + window]. Find the max # of requests we can take.
Notes:
Solve for each user independently, for a given user find all their requests in sorted order, greedily take earlier elements (it is never worse to take some early request as it can block up to at most 1 other request). I tracked the elements in a queue. And before we try to take a new request we drop out the left if we passed that window. If we cannot take a request skip it.
Solutions:
3435. Frequencies of Shortest Supersequences
Problem Summary:
We have N <= 256 bigrams. Each bigram means we need that word to appear as a subsequence, so "ab" and "ba" means we need at least aba. Find all the shortest supersequences that contain every bigram, but don't double count permutations, e.g. "aa" and "ac" both "aac" and "aca" work but we just use one as a result. At most 16 unique letters are included.
Notes:
First observe we can brute force try things if we cap the maximum letter frequency to 3. We can prove that no letter would be needed 3 times because we can always wrap the inner string X: ABC (X) CBA. By putting 2 on the outside we can form any bigram B->A or A->B. There are 2^16 possible bitmasks of doubled letters, we can test each one. We must double letters that have a word "xx". Now any edge with those doubled letters we don't consider part of the graph. Are the remaining edges doable? If the edges left by only letters that appear once, form a cycle, it is not doable, otherwise it is.
Drill Type:
Implementre-read notes, practice implementing cycle detection cleanly, maybe with and without kahn's
Solutions:
1356. Sort Integers by The Number of 1 Bits
Problem Summary:
do what the title says
Notes:
custom sorter
Solutions:
3521. Find Product Recommendation Pairs
Problem Summary:
Given a SQL table of product purchases and product info, find how many times a user purchased two different products (basically for a recommendation alg type of thing) and report those with >= 3 users who bought those similar items
Notes:
great implementation practice, needed multiple joins, count distincts, etc
Solutions:
177. Nth Highest Salary
Problem Summary:
Given a SQL db of salaries find the Nth highest, also N can be negative for some reason which we should return null
Notes:
I used LIMIT 1 OFFSET N - 1, and had to do an outer If ... ELSE for when N < 1.
Solutions:
358. Rearrange String k Distance Apart
Problem Summary:
We have a string length <= 3e5 of letters. Re-arrange it so no two letters are < k apart, or return impossible
Notes:
We should greedily place the most frequent letter we can- imagine there are some small speedups like a heap or O(1) but I basically did a 26n type thing
Drill Type:
Mindsolvere-read solution
Solutions:
2333. Minimum Sum of Squared Difference
Problem Summary:
We have N <= 1e5 length arrays nums1 and nums2. And k1, k2 <= 1e9. For k1 we can increment or decrement a number in nums1 by 1. k2 is for nums2. We want to minimize the sum of squares of differences across the i-th pairwise groups. so (nums1[i]-nums2[i])**2 summed for all i. Compute that min sum.
Notes:
Note increasing nums1[i] or decreasing nums2[i] results in the same remainder so we really just have "totalOperations". We greedily reduce the largest diffs first. But since totalOps is big we process them kind of like towers, shaving them down: || ||||| ||||||||||| So start the the largest tower, keep going and seeing if we can adjust all previous towers to the current one. Once we cannot we can do some math. Really it's just a bit of implementation.
Solutions:
408. Valid Word Abbreviation
Problem Summary:
We have a string for a word and an abbreviation like b2km3 = b 'oo' km 'ark', tell if the abbreviation forms the word
Notes:
Just decompose the blocks into letters and numbers and validate with 2 pointers
Solutions:
457. Circular Array Loop
Problem Summary:
Given a functional graph and each node has a non-zero value, determine if there is a cycle with all positive or with all negative values. Follow-up: Do in O(1) space
Notes:
This is good practice for cycle detection, marking seen / paths is a bit weird. I ended up using a seen + a path set. We need both. For instance this graph: 2->1->1 (goes to itself). If we explore 1 first then 1 is in seen. If we start from 2 now and hit 1, we cannot just check if 1 is in seen to see if we have a cycle, since it was seen from an earlier path. So we need to check if 1 is in path. I used bottom up iteration instead of dfs recursion. O(1) we can do tricks like marking things as seen or in paths by padding the integers with other bits. Or tortoise + hare to detect a cycle and we can 0 out a cycle or something like that to prevent re-exploring(?)
Drill Type:
Implementimplement an O(n) space solution, either recursion or iteration, just re-read notes for tortoise + hare
Solutions:
3848. Check Digitorial Permutation
Problem Summary:
Given a number, take the sum of the factorials of its digits, and check if that sum is a permutation of the initial number
Notes:
Just do what it says
Solutions:
3847. Find the Score Difference in a Game
Problem Summary:
There are two players, one is active. The active player switches based on certain conditions. Whoever is active scores the i-th # of points. How many points do they get?
Notes:
Just simulate
Solutions:
3849. Maximum Bitwise XOR After Rearrangement
Problem Summary:
Given 2 binary strings we can re-arrange the second, form the max XOR
Notes:
just greedy bit by bit
Solutions:
2286. Booking Concert Tickets in Groups
Problem Summary:
We have N <= 5e4 rows of seats. Each row has M <= 1e9 seats. We need to see the earliest row we can seat K <= 1e9 *adjacent* people, and place them. We also can "scatter" so place K people non-adjacent, still as early rows / columns as possible, up to a provided upper row threshold. Support these queries.
Notes:
To find the earliest row we can place I used a min segment tree tracking the earliest un-sat seat per row, now it's a seg tree walk to find the leftmost row with a seat <= X. Could use a max seg tree and store seats remaining. For scatter same thing we can check the sum of the first maxRow remaining seats. If it isn't enough seats we cannot scatter. If it is, we can loop through one row at a time placing them. This amortizes since we only continue the loop if we fill a row. We track the latest filled row so far. Important prune we need to break once we've placed everyone in the scatter, otherwise placing 1 person up to row 50,000 we would loop over all 50,000 rows each time.
Drill Type:
Mindsolvere-read notes
Solutions:
765. Couples Holding Hands
Problem Summary:
We have n <= 30 couples numbered 0...2n-1. We want them to sit together like (1, 0) (4, 5) (3, 2). We can swap any two people. Min # of swaps to satisfy?
Notes:
There is a greedy n^2 solution (easily optimized to N). Scan every pair. If it is already a couple then continue. If not, we can arbitrarily pick one of the two, and find the right replacement for them, and swap those 2. To find the right replacement in O(1) we can track the people->indices to make it O(n) overall. Also a nice trick to find the right paired partner is to use x^1, so (5, X) then 5^1 = 4 which means we require a 4, or (2, X) 2^1 is 3 so we require a 3 The proof of correctness doesn't feel airtight, some thoughts: -If we have (A, X) (B, Y) and we want (A, B) (X, Y) it doesn't matter which of the two we swap -Otherwise, when we swap we are sending away a person to a pair that was already broken, that pair cannot become more broken -Kind of cycle decomposition vibes and reducing cycle sizes by 1 but the way of modeling cycles felt weird
Drill Type:
Mindsolvere-read notes
Solutions:
2421. Number of Good Paths
Problem Summary:
We have a tree of N <= 3e4 nodes with values <= 1e5. Count the # of paths where the two endpoints are the same, and no path value has a higher value.
Notes:
I used small to large merging. We propagate up a hashmap of value -> number of upwards paths where we haven't been blocked. As we aggregate we multiply children counters that are >= our root value, to update our result. We also update our hashmap going upwards. After I cleared out any keys with value < root value because it gets blocked. Linear solution is DSU, we sort edges by max(node1, node2). If we merge these in order we can combine only paths with that maximum element from our two components.
Drill Type:
Mindsolvere-read notes for dsu solution
Solutions:
2500. Delete Greatest Value in Each Row
Problem Summary:
We have a 2D grid of numbers, each turn we delete the max from every row at the same time, and add the max of those to our score. Final score after we delete the entire grid?
Notes:
We can sort each row independently and take those maxes. Can bucket sort also.
Solutions:
1944. Number of Visible People in a Queue
Problem Summary:
We have N minions in a row all with different heights. A minion at index i can see one at index j, i<j, if all minions in between them are shorter than the shortest of the i-th and j-th. How many can each minion see?
Notes:
There is some sort of linear monostack solution but I didn't really get it. My technique was: We can see the minion directly on the right. From that minion, any to the right shorter than it we cannot see. So go to the next one bigger than it. We can see that. Repeat until we reach a minion taller than our initial one. I used a monostack to generate the next greater and then binary lifting for n log n.
Drill Type:
Mindsolvere-read notes, don't worry about understanding the plain monostack
Solutions:
1418. Display Table of Food Orders in a Restaurant
Problem Summary:
We have food orders for customers + tables + the food they ordered. We have to output a dataset that shows how much of each food type each table ordered.
Notes:
Just uses hashmaps to track things
Solutions:
761. Special Binary String
Problem Summary:
We are given a special binary string of length <= 50. A special binary string has an equal amount of 0s and 1s, and all prefixes have at least as many 1s as 0s. We can swap two adjacent special binary substrings any number of times. Find the lexicographical largest resulting string we can make.
Notes:
Think of our binary strings like mountains where a 1 goes up and a 0 goes down. Then a special binary substring is a mountain that touches the ground once. We can decompose our string into as small binary substrings as possible as our primitive blocks. Like '1010' could decompose to ['10', '10']. It's always okay to decompose the pieces because we can represent any swaps of larger aggregates, using these smaller pieces. Like swapping X and Y which are large special substrings that are adjacent, if we decomposed them into pieces, we could swap Y with the last X piece, the second to last X piece, and so on, to perform the X<>Y swap. Once decomposed we have subproblems so we can recurse on those. Our base case is if we have a single block, in which case we must start with a 1 and end with a 0. We're allowed to greedily take the inside which is now special at a higher height by 1. There's some bitset thing too but not sure if it actually is useful
Drill Type:
Mindsolvere-read notes, I guess think about the decomposition chain of thought more.
Solutions:
655. Print Binary Tree
Problem Summary:
Given a binary tree we need to print it in a matrix grid following certain rules
Notes:
Just do dfs(r, c, node) and construct the output result, there is also a BFS version but I think it's basically the same
Solutions:
558. Logical OR of Two Binary Grids Represented as Quad-Trees
Problem Summary:
We are given two quad trees of bit regions and need to merge them. A quad tree node can be a leaf if the entire region it represents is all 0s or all 1s. Otherwise it has 4 children.
Notes:
If quadTree1 is a leaf and value 1, the bitwise OR of this entire region is 1 for everything so we can return quadTree1, otherwise return quadTree2. Same for vice versa. If they are not leaves, we recurse on the 4 quadrants. We compress things if all the values are the same.
Drill Type:
Mindsolvequick re-read notes/code
Solutions:
270. Closest Binary Search Tree Value
Problem Summary:
Given a BST, find the closest value to a target, if equidistant pick the smaller one
Notes:
O(height): We can do this in one pass while loop, maintain our best distance and number, if our node is too big go left, else right. Also there is an O(k) solution where k is the index of the best element and is much smaller than tree height. To be honest didn't fully understand but it is fine
Drill Type:
Mindsolvequick re-read code for one-pass
Solutions:
922. Sort Array By Parity II
Problem Summary:
Sort an array so evens are at even positions and odds are at odds, it is always doable for the input
Notes:
Two pass is obvious but we can do one pass with some sort of two pointers solution with reads and writes, review implementation class Solution(object): def sortArrayByParityII(self, A): j = 1 for i in xrange(0, len(A), 2): if A[i] % 2: while A[j] % 2: j += 2 A[i], A[j] = A[j], A[i] return A
Drill Type:
Mindsolvereview and understand implementation
Solutions:
544. Output Contest Matches
Problem Summary:
Given N contestants output their final matches, like round one 1 battles N, 2 battles N-1, it's kind of a string builder question
Notes:
I just iteratively built the result, mine is n log n, there is a linear write I didn't look into
Solutions:
1008. Construct Binary Search Tree from Preorder Traversal
Problem Summary:
Given a preorder traversal construct a BST
Notes:
recursive, root is the first element, find the first element bigger than root, that is right subtree, naive is O(n^2) if we scan over and over but can optimize to O(n) if we precompute the first biggest on the right for each element via stack
Solutions:
1389. Create Target Array in the Given Order
Problem Summary:
We have N instructions to insert numbers at different indices in an array, construct the final output.
Notes:
n^2 is easy, seems like n log n can be done in a few ways: 1/ having some sorted container set where we have (1, number) (2, number) and when we want to insert at a given position we make a fraction like (1.5, number) works 2/ we can do something with a fenwick tree, looping backwards, where we count the # of empty cells in a prefix [0, i] or something like this 3/ I think a PBDS / order-statistic tree or a treap or something like that can basically do #1 but without the fraction key trick
Drill Type:
Mindsolvere-read notes for n log n
Solutions:
2689. Extract Kth Character From The Rope Tree
Problem Summary:
We have this cursed structure binary tree where nodes either have strings (if they're leaves) or lengths representing the sum of leaf lengths in that subtree, find the K-th character
Notes:
Basically we can always recurse to one child and spend only O(height) time can use O(1) space if iterative
Solutions:
3030. Find the Grid of Region Average
Problem Summary:
A region is a 3x3 grid of pixels where the difference of any two adjacent pixels is <= some threshold. For each pixel, find the average of the averages of all regions it is a part of.
Notes:
Basically a bunch of helper functions, isRegion, regionAverage, etc, I'm sure we can optimize if the 3x3 is bigger
Solutions:
3711. Maximum Transactions Without Negative Balance
Problem Summary:
We have N <= 1e5 transactions, -1e9 <= arr[i] <= 1e9 We process the transactions in order but our balance can never go below 0, max # of transactions we can take?
Notes:
We use a greedy: -Take left to right and always take positive transactions, track our running balance -If we can take a negative transaction, do it for now, but store our taken negatives somewhere -If we cannot take a negative transaction, see if we can exchange with a better one that we already took Idea that failed: Take all positive, then process negatives in order (like -1 first before -100), use a segment tree to see if the prefix we have taken so far is big enough to take this negative. Doesn't work because there could be some suffix segment that dips below: # [-6,10,-7,-5,5] We take 10 and 5 so we get 15, then we try -5 first that works, now we try -6 we cannot take it due to prefix, now we try -7 it looks like we can take it because the suffix is 0 and prefix is 10 but doesn't really work like that Also tried some ideas around seg tree dp "max # of transactions per balance" or "max balance per # of transactions" but didn't see anything good
Drill Type:
Mindsolvere-read notes
Solutions:
3846. Total Distance to Type a String Using One Finger
Problem Summary:
Given a keyboard (each letter on a given row and column) find the distance we move to type out a word
Notes:
Just map each letter to its position and get the distance differences
Solutions:
56. Merge Intervals
Problem Summary:
Given N <= 1e4 intervals [start, end] <= 1e4 return them merged
Notes:
1/ Sort and handle merging, not too hard with basic logic 2/ Some sort of weird sweep line or bucket sort can make it linear w.r.t. the size of the space
Drill Type:
Mindsolvequick notes re-read
Solutions:
50. Pow(x, n)
Problem Summary:
compute x^n. - 2^31 <= n <= 2^31. Guaranteed the answer is small (no mod needed)
Notes:
top down is easy and we just use recursion not even dp really bottom up is tricky basically 5^13 is 5^8 * 5^4 * 5^1 (exponents all powers of two) so we loop through the bits of the power and keep squaring the base to double its exponent and multiply res by base when the bit is set, while loop version kind of works the same way
Drill Type:
Mindsolvere-read notes and for loop bottom up method in code
Solutions:
49. Group Anagrams
Problem Summary:
Find all indices which contain the anagram of an input string
Notes:
standard have + need trick, I bet we could also do some sort of hashing on prime product % MOD + hashing on sum but not listing
Solutions:
3573. Best Time to Buy and Sell Stock V
Problem Summary:
We have stock prices over time, we can buy and sell or short and repay, only 1 tx at a time allowed, max profit with at most k transactions?
Notes:
dp(i, isBuyOpen, isShortOpen, txLeft) is 4*n*k Alien trick can do n log K https://leetcode.com/problems/best-time-to-buy-and-sell-stock-v/solutions/7419591/on-log-k-alien-trick-wqs-binary-search-b-r5h4/
Solutions:
3577. Count the Number of Computer Unlocking Permutations
Problem Summary:
We have N computers with different complexities. Computer 0 is unlocked. We can take a computer L and unlock a computer R (those are indices) if L is unlocked and it has a lower complexity. How many permutations make it so we can unlock everything?
Notes:
If the 0th computer is the minimum we can unlock all other computers with it. If it is not, then whatever is the minimum is not unlockable. So we count the # of permutations of size n-1. someone also did with stack + binary-search: [https://leetcode.com/problems/count-the-number-of-computer-unlocking-permutations/solutions/6821937/monotone-decreasing-stack-binary-search-intuition-code-comments/](https://leetcode.com/problems/count-the-number-of-computer-unlocking-permutations/solutions/6821937/monotone-decreasing-stack-binary-search-intuition-code-comments/)
Drill Type:
Mindsolvere-read notes / way of thinking for first method
Solutions:
1695. Maximum Erasure Value
Problem Summary:
Find the maximum sum consecutive subarray with all unique elements
Notes:
standard variable window, expand while unique and update sum
Solutions:
1710. Maximum Units on a Truck
Problem Summary:
We have different box quantities and units per box, and a truck size, find the max # of units
Notes:
Sort by max units per box first, or use bucket sort
Solutions:
1365. How Many Numbers Are Smaller Than the Current Number
Problem Summary:
Given an array of N <= 500 numbers <= 100 return an array for each number with a count of how many numbers were less than it
Notes:
We can do bucket sort on size 100 for each bucket get the count then make a prefix counter for elements <= X then return the mapped array
Solutions:
2989. Class Performance
Problem Summary:
Given a SQL table of scores for 3 assignments per student find the max total score - min total score across all students
Notes:
-- Write your PostgreSQL query statement below SELECT (MAX(tot) - MIN(tot)) AS difference_in_score FROM ( SELECT (assignment1 + assignment2 + assignment3) AS tot FROM Scores ); worked but if you do SUM(a1 + a2 + a3) then you need to group by student ID or it sums up everything, I think the sums of the sums of all 3 columns
Solutions:
2881. Create a New Column
Problem Summary:
Given a pandas dataframe add a column which has doubled values of another column
Notes:
we can use normal python syntax because pandas overrides the get and setitem functions and the __mul__ function for applying the *2 across the entire vector
Solutions:
2884. Modify Columns
Problem Summary:
Given a pandas dataframe return it with all salaries doubled
Notes:
We can do dataframe['salaries'] *= 2 This works because in python we can define custom behavior for __getitem__ which is responsible for [...] syntax Same with the set item and multiplication operators
Solutions:
2879. Display the First Three Rows
Problem Summary:
Given a pandas dataframe return the first three rows
Solutions:
3842. Toggle Light Bulbs
Problem Summary:
We have 100 lightbulbs. There are N queries which toggle them. Report the bulbs on at the end.
Notes:
just track them with a boolean array lol, could even use a bitmask but probably not faster
Solutions:
3841. Palindromic Path Queries in a Tree
Problem Summary:
Given a tree of letters of N <= 5e4 nodes and Q <= 5e4 queries, support: 1/ Query a path [a, b] to see if the letters along that path can be re-arranged to form a palindrome 2/ Update a letter
Notes:
-We can use ETT + seg tree where each node stores a bitmask of the parities, this is logN per query How this works: Each node stores a node-to-root bitmask path, to get a simple path we can do the two node-to-root paths XORd with their LCA-to-root (via binary lifting) When we update a node, everything in its subtree gets a new node-to-root path so we can either do a lazy seg tree XOR update or update the left and right points (range update + point query means we don't need a lazy tree) and just use a regular seg tree to get a prefix XOR query -We can use HLD where each node stores a bitmask, this is log^2N per query -Even HLD where each node stores an array of size 26, which is 26*log^2N per query, worked for me in contest -Apparently there is some LCT solution too -Also if re-arranging is not allowed we can store forward and rev hashes to answer that different question
Drill Type:
Implement-implement hld -implement ett
Solutions:
3840. House Robber V
Problem Summary:
Given N <= 1e5 houses each with a color and a value we cannot rob two adjacent houses if they are the same color, max profit?
Notes:
Just knapsack dp but we skip the next option if it shares a color, problem worded poorly
Solutions:
3839. Number of Prefix Connected Groups
Problem Summary:
Given N <= 5000 words of lengths <= 100 and a K <= 100. A group is all words that share a prefix of size k. Find the # of groups with at least two words.
Notes:
Counter based on prefix of size k, basically naive
Solutions:
3838. Weighted Word Mapping
Problem Summary:
Just a basic string manipulation question
Notes:
'ord' is your friend in python
Solutions:
67. Add Binary
Problem Summary:
Given two numbers in binary strings, add them
Notes:
We can go right to left and handle carry bits and whatnot, can also do it without + symbol using ^ and & (fb follow up) I didn't do that though it is annoying
Solutions:
1667. Fix Names in a Table
Problem Summary:
Given a SQL table of users with names, fix each name so only the first letter is uppercase and the rest are lowercase, ordered by user_id.
Notes:
Used CONCAT(UPPER(LEFT(name, 1)), LOWER(SUBSTRING(name, 2))) to capitalize the first letter and lowercase the rest. Classic string manipulation combining UPPER/LEFT for the first character with LOWER/SUBSTRING for the remainder.
Solutions:
1280. Students and Examinations
Problem Summary:
Given SQL tables of students, subjects, and examinations, report how many times each student attended each exam including zeros.
Notes:
kind of a messy cross join with a left join and count on a column to filter out non negatives
Solutions:
2990. Loan Types
Problem Summary:
Given a SQL table of loans with user_id and loan_type, find all distinct user_ids that have at least one Refinance and at least one Mortgage loan type.
Notes:
have to do having count distinct inside the having filter, cannot group by user_id + loan_type because that forms one group for each composite combination
Solutions:
3172. Second Day Verification
Problem Summary:
Given a SQL table of emails and texts, find user IDs of those who verified their sign-up on the second day.
Notes:
standard join and interval +1 to add dates
Solutions:
1661. Average Time of Process per Machine
Problem Summary:
Given a SQL table of machine activity with start/end timestamps, find the average processing time per machine rounded to 3 decimals.
Notes:
just a round and avg with a join
Solutions:
1729. Find Followers Count
Problem Summary:
For each user, count how many followers they have. Order by user_id.
Notes:
GROUP BY user_id, COUNT(follower_id), ORDER BY user_id
Solutions:
613. Shortest Distance in a Line
Problem Summary:
Find the shortest distance between any two points in a SQL table of X-axis positions.
Notes:
Self-join with p1.x < p2.x, then MIN(p2.x - p1.x)
Solutions:
1075. Project Employees I
Problem Summary:
Given a SQL table report the average experience years of all employees for each project, rounded to 2 digits.
Notes:
just a join group by and round
Solutions:
Counting Bishops
Problem Summary:
Count the number of ways K bishops can be placed on an NxN chessboard such that no two attack. K <= N^2. N <= 500.
Notes:
Observe K at most is ~2N because that is how many diagonals we have. Decompose into black and white cells since they can never attack. Then we will solve for placing X in the black section and K-X in the white section. Rotate all of a cell color type by 45% now it forms something like this: x x. x. x x x x x x x x x x For each row and column, only one bishop can exist. If we enumerate these in sorted order, so [1, 1, 3, 3, 5] we can track the # of ways to place X bishops. We know previously placed ones remove spots from the current row and we can use combinatorics. We need to get ways[placed] for all placed 1...k. I couldn't figure out how to do it top down, dp(i, placedSoFar) wasn't working because I can't put a cap on how many we place, might be some workaround but I did bottom up, n^2
Drill Type:
Mindsolvere-read notes since the 45 degree trick and using bottom up were hard
Solutions:
2863. Maximum Length of Semi-Decreasing Subarrays
Problem Summary:
Given an array of numbers find the longest "semi-decreasing" array, which means the left edge is > than the right edge, or 0 if it does not exist
Notes:
n log n with suffix min and binary search is trivial but there is a cool linear: first, only left edges that are prefix maxes matter, among those, the right edge monotonically moves right, so we can do an O(n) sliding window type of thing leaving out sorted containers / seg tree / etc solutions
Drill Type:
Mindsolvere-read notes / glance at code if notes are confusing, for the O(n) version
Solutions:
807. Max Increase to Keep City Skyline
Problem Summary:
Given an MxN board of buildings, find the max heights we can increment across the building such that none of the 4 skylines change
Notes:
We can increase each cell to the smallest of the max in that row and column, n*m time
Solutions:
2674. Split a Circular Linked List
Problem Summary:
Given a circular linked list, split it into two circular linked lists at the midpoint
Notes:
Count size first, then split in half
Solutions:
419. Battleships in a Board
Problem Summary:
Given an M x N board of cells determine how many battleships are there. A battleship is a 1x? sized row / column. Can you do it in one pass with no memory?
Notes:
One pass version is to count top left cells, which either are the vertical or horizontal start of something
Drill Type:
Mindsolvere-read notes because the one pass is cool
Solutions:
2184. Number of Ways to Build Sturdy Brick Wall
Problem Summary:
We have bricks of height 1 and various widths <= 10. For each given width, we have an infinite supply. We have to build a wall of height <= 100, but no two cracked in adjacent rows can line up. How many ways can we do this?
Notes:
Constraints are really small so we can dp bitmask it. We can generate all bitmasks that are doable (1 in the mask represents a crack at that width from the left), and how many ways each one can be done. We can speed up by caching for each mask, valid adjacent masks too. Then the dp is dp(row, aboveMask) and we loop through adjacent masks and the # of ways they can be done. I think matrix exponentiation can solve this for a really big height too!
Drill Type:
MindsolveReread notes + matrix note
Solutions:
1581. Customer Who Visited but Did Not Make Any Transactions
Problem Summary:
We have SQL tables of visits and transactions, find the count of visits, per user, without any transactions
Notes:
JOIN and GROUP BY
Solutions:
3059. Find All Unique Email Domains
Problem Summary:
Given a SQL table of emails, count emails by the domain, ending in .com only
Notes:
split_part can split a field, and LIKE can make sure it ends in .com
Solutions:
2329. Product Sales Analysis V
Problem Summary:
Given a SQL table of Sales and Products find total spending by person
Notes:
JOIN the tables, GROUP BY user, SUM the spending
Solutions:
2837. Total Traveled Distance
Problem Summary:
Given a SQL table of users and rides, find the total ride distance per user
Notes:
a left join, coalesce, and group by worked for me, not the cleanest
Solutions:
2480. Form a Chemical Bond
Problem Summary:
We have a SQL table of elements and if they are metal or non metal, find all metal + nonmetal pairings
Notes:
cross join
Solutions:
1623. All Valid Triplets That Can Represent a Country
Problem Summary:
Given 3 SQL tables of students, return a list of the cartesian product where no 2 students have the same name or ID
Notes:
double cross join and some WHERE filtering
Solutions:
3778. Minimum Distance Excluding One Maximum Weighted Edge
Problem Summary:
Given an undirected, weighted graph of 5e4 nodes, find the minimum distance to go from 0 to n-1 where we can skip one occurrence of the maximum edge.
Notes:
Equivalent to just skipping any 1 edge, since the best result with that is the same. I used dijkstra with minDistWithSkipUsed and minDistNoSkipUsed. We could also do one dijkstra and for each edge treat it as the skipped one and use the end points.
Drill Type:
ImplementThis is one of the dijkstra I will implement, also re-read the second notes idea about skipping an edge
Solutions:
Grid Paths II
Problem Summary:
Given M traps (x, y). M <= 1000, x,y <= 1e6, we can travel from 1,1 down and right. We want to reach N,N, but cannot hit a trap how many paths can we do this?
Notes:
To compute going from 1,1 to N,N without traps we can imagine interleaving D and R moves. We have a sequence of size D+R and need to select D unique buckets to put the Ds in (or R to put the Rs in). So D+R choose D. This is like (D+R)! / (D!) * (R-D)! Now imagine reaching a trap for the first time (no previous trap got us stuck). We could have reached this trap using those binomial coefficient ways but we need to loop over previous traps, that actually came before us in both X and Y, and remove paths that got blocked by that. So we take the previous DP * the new combinatorics paths. We don't worry about, say reaching 10,10, and iterating on a previous blocked 5,5 state, which can later get blocked by 7,7 again, it does not actually double count things if you think about it
Solutions:
Counting Sequences
Problem Summary:
Given k <= n <= 1e6, compute the # of sequences that use every digit from 1-k at least once, of length N
Notes:
We can count sequences using 1-k (but can skip digits) by just doing k^n % MOD. Now we need to subtract sequences missing a single number. There's nCk(n, 1) options to pick this missing number, and (k-1)^n % MOD ways to generate lists when missing this number. But now we need to re-add sequences missing two numbers, because they got double subtracted
Drill Type:
ImplementImplement including the incl-excl, inv fac, combinatorics, and just all required code for this
Solutions:
2853. Highest Salaries Difference
Problem Summary:
Given a SQL table of salaries find the max difference between the marketing and engineering department salaries
Notes:
Use a subquery to get the two maxes and then an outer query to diff them
Solutions:
2669. Count Artist Occurrences On Spotify Ranking List
Problem Summary:
Given a SQL table of spotify songs find the # of occurrences per artist
Notes:
COUNT and GROUP BY
Solutions:
2668. Find Latest Salaries
Problem Summary:
Given a sql table of salaries over years find the max salary per employee
Notes:
Use MAX and group by
Solutions:
1795. Rearrange Products Table
Problem Summary:
We have a SQL table with a product id, and store1 store2 store 3 columns. We need to reformat the table to have those as values under the store column.
Notes:
The key is to union 3 tables
Solutions:
3837. Delayed Count of Equal Elements
Problem Summary:
We have a list of numbers with length <= 1e5 and a k <= 1e5. For a given index number, the delayed count is the number of indices on the right, at least k away, with the same number. Compute this count for each index.
Notes:
We can put each number type bucket of indices separately and solve those independently. Either with binary search or note the right edge only incrases so we can use 2 pointers for a linear solution.
Drill Type:
MindsolveRe-read the linear notes / code since sometimes I miss this
Solutions:
Empty String
Problem Summary:
Given a string of <= 500 letters, we can remove an adjacent pair of letters. Find the # of unique sequences of moves to clear the string.
Notes:
We know our leftmost letter must be paired with some other letter in the deletion, for example: ABBAABBA that leftmost A could be paired with the first A and the BB is deleted, or even the last A and everything inside is deleted. So in dp(l, r) loop on the inner letters that can be paired with the leftmost letter. Now we have 3 pieces: 1/ The piece on the right which is a sub-problem 2/ The inner part on the left which is a sub-problem 3/ The single deletion we make How many combinations does this form? The piece on the right consists of some fixed # of moves (length/2), same with the inner part on the left. These are independent and thus those moves can be intertwined, but we have to multiply by the # of different dp ways for each. But what about that single move? That can occur anywhere after the entire inner part has been deleted. So we are basically interleaving B moves (right length / 2) and A+1 moves (left length / 2, +1 for the special move). If we are interleaving XXX and YY we basically have 5!/(3! * 2!) unique strings so we can compute that.
Drill Type:
Implementshould re-read notes and re-solve this, ideally with invFac too
Solutions:
334. Increasing Triplet Subsequence
Problem Summary:
Given an array of N <= 1e5 numbers, determine if there is a strictly increasing triplet subsequence.
Notes:
The O(n) time O(1) space solution is to track the smallest and secondSmallest numbers kind of like a state machine
Drill Type:
Mindsolvereview the optimal notes solution
Solutions:
3. Longest Substring Without Repeating Characters
Problem Summary:
Find the longest string without duplicate chars
Notes:
Basic variable window, can teleport left edge if needed, can also bin search on answer + fixed window but not listing
Solutions:
422. Valid Word Square
Problem Summary:
We have a 500x500 grid with letters. Determine if every row word is the same as the column
Notes:
We can just brute force check every row+column in n*m time
Solutions:
53. Maximum Subarray
Problem Summary:
Find the maximum subarray sum with negatives in the array
Notes:
Kadane's, no need to practice since I have a CSES question marked
Solutions:
152. Maximum Product Subarray
Problem Summary:
Find the maximum product subarray of an array with numbers that can be negative too, guaranteed answer doesn't get huge
Notes:
dpMin and dpMax like kadane's, note they both get set to 1 as identity initially
Drill Type:
MindsolveHonestly just glance at code quickly, identity kind of threw me off
Solutions:
984. String Without AAA or BBB
Problem Summary:
Given A, B <= 100 construct a string with A a's and B b's, but not aaa or bbb occurrence. It is guaranteed a valid string exists.
Notes:
We can just put the bigger frequency if possible, otherwise smaller one.
Solutions:
438. Find All Anagrams in a String
Problem Summary:
Given two strings s and t, find all indices where t[i:i+len(s)] are anagrams of s
Notes:
Either have need trick or we can do prime number hashing with mod but I won't list that lol
Solutions:
1930. Unique Length-3 Palindromic Subsequences
Problem Summary:
Find the # of palindromic subsequences of length 3
Notes:
One way is to look at the leftmost and rightmost occurrence of each letter type, and query how many unique letters are in the middle, I think that is 26n though I also just iterated on the middle letter and iterated on the 26 possible outer letters and added them to a seen set, still 26n We could also for each pair of 2 letters, find the leftmost index of the first letter, the binary search for the leftmost index of the second letter that is greater than that (we can create the indices for each letter time in O(1*n) total), then check if the outermost letter is on the right, this is N + 26^2 * logN
Drill Type:
MindsolveRe-read the third solution because it is cool
Solutions:
1332. Remove Palindromic Subsequences
Problem Summary:
We have a string of a's and b's, we can remove a palindromic subsequence in one move. How many moves to clear the string?
Notes:
If palindrome, 1, otherwise 2
Solutions:
1055. Shortest Way to Form String
Problem Summary:
We have a source and target string <= 1000. Find the minimum number of squashed together sources so that target is a subsequence of it.
Notes:
Well the constraints are pretty small so we could brute force it. But a more advanced way is for each index in source, for each letter type, find the earliest position to go to (dp). Now we enumerate the target string and can in O(1) find our pointer in the source string. This is like 26S + T. There's also some log based solution with binary search and inverted indices but I didn't read it.
Solutions:
392. Is Subsequence
Problem Summary:
See if s is a subsequence of t
Notes:
Basic two pointers
Solutions:
2831. Find the Longest Equal Subarray
Problem Summary:
Find the longest subarray where we can delete up to K elements and all the remaining elements are the same. N <= 1e5.
Notes:
Sliding window as long as the width - K is <= max frequency. I used the frequency checker structure which can add, remove, and get max frequency in O(1). See those notes too: # O(1) add a number to the structure # O(1) remove a number from structure # O(1) find max frequency of an element # It works by mapping: # number -> frequency # frequency -> list of numbers # When we pop an element the old bucket of numbers with that frequency needs updating, we can do it in O(1) by swapping that with the last element of the array # then popping (swap and pop trick), but this requires tracking the position of every element in the buckets too # If we don't want that, we can just track a number -> frequency and a frequency -> count of numbers, easier to implement but now we can't get all numbers of a given frequency
Solutions:
2607. Make K-Subarray Sums Equal
Problem Summary:
In an operation we can increment or decrement a number by 1. We have an array of size N <= 1e5 with values <= 1e9. It is circular. Minimum # of operations so that the sum of every subarray of size K is the same?
Notes:
I had some weird observations about trying to form safe cycles, for instance if K=2 we can do something like: A B | A B | A B But if our length is not divisible by 2: A B | A B | A B | A It fails because we have AA at the circular junction, and we are forced to do A A A A A A A instead. Ultimately I tried a bunch of casework style stuff but it wasn't working. I missed the sharp observation: Any two indices spaced by K must be the same. If not, we can show a transition where the sum changes. If all spaced by K are the same, we can prove every subarray is the same size. So we can kind of find these cycles and solve it in O(n). My initial solution at the top was some cursed idea to find all potential group sizes (A B means a group of 2) that are factors of both K and N, and test the score if we use that sized group. I had used pollard rho to find those factors of K and N faster than trial division, but not putting in notes
Drill Type:
MindsolveRe-read notes
Solutions:
777. Swap Adjacent in LR String
Problem Summary:
We have strings like LXXRLRXLLR We can do XL -> LX and RX -> XR. Can we make the first string into the second?
Notes:
First make sure the order of L and R is equal. Bad cases are if we have an L in the first string on the left of the second string, like: LX XL And opposite for R, this is a bad case: XR RX My code was kind of elegant, I track surpluses and fail it we don't have enough
Drill Type:
MindsolveRe-read code / notes, have a bad feeling this is an interview question and it is kind of tricky despite that I got it quickly and cleanly
Solutions:
3067. Count Pairs of Connectable Servers in a Weighted Tree Network
Problem Summary:
We have a weighted tree of N <= 1000 nodes. Two nodes A, B are connectable by C if the distance A<>C and B<>C are both divisible by signalSpeed, and no edges are shared on the path A<>C and C<>B. For each node, output how many pairs exist where that node is C.
Notes:
For a given node imagine it as the root. We basically make a new tree with this node as the root (since N <=1000). Now this node will be C, and A and B have to come from 2 nodes in different subtrees. First compute the distance from all nodes to the root with a normal DFS. Now for each child of the root we get a counter of how many elements in that subtree are divisible by the signalSpeed. We do a basic tree convolution style. N^2 time
Drill Type:
MindsolveRe-read notes / code, code was a bit weird because I had to specifically do this operation at the 1-depth subtrees
Solutions:
Point Location Test
Problem Summary:
Given 2 points p1 and p2, if we walk from p1 to p2 do we have to turn left or right to see p3, or is it on the line?
Notes:
Imagine p1 is the origin and p2 is somewhere in the top right grid (p3 can be anywhere). If the area of this triangle is 0 it is colinear. Recall the area of a parallelogram is base * height. If we have two vectors that form two sides of a parallelogram, say A and B, and an angle theta between them, to compute the height it is sin(theta) * |A| _______ / / / / /_______/ Imagine A is the left-up vector and B is the flat vector. Theta is the angle. H (height) is SOHCAHTOA so sin(theta) = h/|B|. H = sin(theta) * |B|. So area is |A|*|B|*sin(theta). Triangle area is half of this. Cross product of the vectors is also the signed area of a parallelogram so half of that is the signed area of the triangle. If 0, it is colinear. To prove the cross product is the signed area we can imagine a triangle with one point at the origin and two in the top right quadrant. This is always doable because we need an interior angle < 90 which always exists, to fit all points in the top right quadrant. Label the points x1y1 and x2y2 then draw a square around the borders. Subtract the 3 triangles formed and derive the area. See "proof_of_cross_product.HEIC" drawing on computer. But there are some triangles this square construction doesn't work on because it doesn't form 3 triangles, so I don't think this proof is complete. But anyway that simplifies to the cross product. I think depending on the order of the points used we can get a negative or positive numerator, like C-D times -1 is D-C so that's why we get signed areas. And I think if the first point we choose is on the left we get a positive signed area. Thus, we do this construction, and depending on the signed result we are on the left, right, or on the line. My proof is also incomplete because this is just when all the points are positive coordinates but I suppose the math works out or there is a better proof elsewhere.
Drill Type:
MindsolveRe-read notes and code
Solutions:
219. Contains Duplicate II
Problem Summary:
Determine if there are two of the same number <= k indices apart
Notes:
We can do a fixed window and keep a set or we can just track the lastmost index of an element as we iterate
Solutions:
1984. Minimum Difference Between Highest and Lowest of K Scores
Problem Summary:
Find the min difference between the highest and lowest number in a set of K (you can pick) elements from an array
Notes:
Sort the array and do a fixed window / lookup
Solutions:
1876. Substrings of Size Three with Distinct Characters
Problem Summary:
Find the number of substrings of length 3 with all distinct characters
Notes:
Just iterate and do it, we could generalize to X > 3 though
Solutions:
643. Maximum Average Subarray I
Problem Summary:
Find the maximum average subarray of length K
Notes:
standard fixed window
Solutions:
2461. Maximum Sum of Distinct Subarrays With Length K
Problem Summary:
Find the max subarray sum of fixed windows with all distinct numbers
Notes:
Just fixed window and track frequencies and sum
Solutions:
Polygon Area
Problem Summary:
Find the area of an ordered set of points
Notes:
shoelace theorem
Drill Type:
Implementshould be able to implement this alg, probably not understand how it works lol, also remember when shoelace theorem can be used (ordered set of points, can be convex)
Solutions:
3737. Count Subarrays With Majority Element I
Problem Summary:
Find the # of subarrays where `target` is the majority element, N <= 1000
Notes:
brute force
Solutions:
3799. Word Squares II
Problem Summary:
We have N <= 15 words and need to find all valid word squares, like this: D O G I O G O T
Notes:
First thought was backtracking but easier is just n^4 loop.
Drill Type:
MindsolveRe-read code, remember these things: 1/ n^4 over backtracking 2/ Handling duplicates isn't so complex since rotated squares are considered distinct
Solutions:
3699. Number of ZigZag Arrays I
Problem Summary:
Find how many sequences of length N <= 2000 have numbers between [L, R] <= 2000, and are zig-zag sequences (up then down then up and so on).
Notes:
A basic dp(i, prev, prevWasUp) and then for loop on the next number is n^3. Can be optimized with for loop caching / prefix sum dp but brutal constant factor needed bottom up dp. I did not have to make the cache size r-l (meaning if l=1999 and r=2000 I could make the cache size 2000), but I did have to do the rolling dp ndp pf arrays swapping trick to get it to pass in time in C++
Drill Type:
ImplementTest your C++ and prefix sum dp skills
Solutions:
3738. Longest Non-Decreasing Subarray After Replacing at Most One Element
Problem Summary:
We can replace one element in an array. Find the longest mono-increasing array we can make. N <= 1e5
Notes:
If we replace an element we need the previous index decreainsg left and the next index increasing right streaks, we can do this with dp, there is some O(1) space solution I don't know
Solutions:
3736. Minimum Moves to Equal Array Elements III
Problem Summary:
Find the min # of increments to make all elements equal to max
Notes:
Diff max with all elements I think we can do in one pass even
Solutions:
3662. Filter Characters by Frequency
Problem Summary:
Return a string of letters from an input string only keeping letters appearing < k times
Notes:
Just counter and then construct the output
Solutions:
3667. Sort Array By Absolute Value
Problem Summary:
Sort numbers by absolute value
Notes:
Use a custom sorter or bucket sort
Solutions:
3836. Maximum Score Using Exactly K Pairs
Problem Summary:
Given 2 arrays of length <= 100 and a K <= 100 we have to select pairs (i, j) with i from nums1 and j from nums2. All i_x < i_x+1 and all j_x < j_x+1. The score of a pair is nums1[i] * nums2[j]. Max score we can get?
Notes:
dp(i, j, pairsLeft) and we can increment one of the pointers or take the pair
Solutions:
3834. Merge Adjacent Equal Elements
Problem Summary:
Given an array of N <= 1e5 numbers, find the leftmost pair of two of the same number, squash/sum them together, find the final array.
Notes:
We can use a stack and just emulate this behavior
Solutions:
3833. Count Dominant Indices
Problem Summary:
Find the # of indices with numbers > the average of numbers on the right, small N
Notes:
Brute force or just range sum query works
Solutions:
174. Dungeon Game
Problem Summary:
We have a grid with + and - health scores. We cannot have <= 0 health. We start in the top left and can move down/right. What is the min starting health we need to reach the bottom right?
Notes:
We cannot do dp on "min initial health to reach cell X" because we will have varying amounts of ending health which changes answers for further cells. But "min initial health to reach end from cell X" works. We can do this top down. Also binary search on answer and then see if we can reach the end with that much starting health works too (dp stores max health we can get to reach a cell).
Drill Type:
MindsolveRe-read code, note in binary search method I used this pollution technique with -infs, in the top down version note the recurrence relationships are a bit wonky
Solutions:
3742. Maximum Path Score in a Grid
Problem Summary:
Given an N x M (N,M <= 200) gird we want to move from the top left to the bottom right. Each cell incurs a cost and gives a score. What is the max score with cost <= 1000?
Notes:
dp(r, c, currCost) works. We could add the cost BEFORE we enter the cell or WHEN we enter the cell. I found prefixCost (meaning we have to add WHEN we enter the cell easiest). Cool thing about this question is we deal with both costs and scores and they apply the same way, so both are prefix based or both are inclusive based. I wrote both solutions. For bottom up, can do push or pull dp on the matrix also and space optimize by only preserving the prior row which drops a dimension.
Drill Type:
MindsolveRe-read notes on the easier format to implement and also quickly re-read the push/pull concept here
Solutions:
Shortest Routes II
Problem Summary:
Given N <= cities roads and M <= N^2 weighted roads, answer Q <= 1e5 queries for the min distance between two cities.
Notes:
Floyd warshall n^3, I think dijkstra will be too slow
Drill Type:
Implementimplement fw
Solutions:
2217. Find Palindrome With Fixed Length
Problem Summary:
For a given length <= 15 generate the K <= 1e9 palindrome
Notes:
We can do the k-th sequence thing. I used a "passed" variable to track number of sequences we have completely passed but that makes the indexing a bit confusing because we need to reach a k-1 passed state. So maybe currentTerm and initialize it to 1 is easier to do the indexing? Also we can just take the first half and generate the k-th then mirror it
Drill Type:
MindsolveRe-read notes
Solutions:
3798. Largest Even Number
Problem Summary:
Given a string of 1s and 2s we can delete digits to make the largest even number
Notes:
Delete all suffix 1s
Solutions:
3800. Minimum Cost to Make Two Binary Strings Equal
Problem Summary:
We have two binary strings, we can flip a bit in a string for flipCost, swap two in the same string (either string) for swapCost, or swap s[i] and t[i] for crossCost. Min cost to make two strings equal?
Notes:
We count mismatches with 0 in the first string and mismatches with 1 in the first string. The cross ability is actually useful because if we have 2 mismatches with 0 on top and none with 1 on top we could cross first then swap. Three cases: 1/ Use as many crosses as possible, swap and flip the rest 2/ Flip only 3/ Swap as many as possible then flip
Solutions:
3822. Design Order Management System
Problem Summary:
Design an OOP class to add order IDs with prices and types, update a price, cancel an order, and find all orders at a given type and price.
Notes:
We can do O(1) with every method if we use the trick to pop O(1) from the middle of a list by swapping it with the end and popping it. Not needed for the problem constraints though.
Solutions:
1113. Reported Posts
Problem Summary:
Given a SQL table of posts find reported ones
Notes:
grouping and counts
Solutions:
3831. Median of a Binary Search Tree Level
Problem Summary:
Given a BST find the median on the K-th level
Notes:
We can use BFS to get the level order and easily find median or even DFS and quick select
Solutions:
1809. Ad-Free Sessions
Problem Summary:
Given a SQL table with watch sessions and a table with ads find sessions which didn't have any ads
Notes:
The intersection / exclusion logic was tricky here. If you LEFT JOIN where the customer matches AND and ad is in range, and then filter where the ad is null, it is always sessions with no ads. Either the set of matches is non-empty then we only get rows with ads in the session or it was empty.
Solutions:
1633. Percentage of Users Attended a Contest
Problem Summary:
Given SQL tables for contest registrants and users find the percentage of people who registered for each contest
Notes:
We can grab the count of all users with one SELECT and use that in our math
Solutions:
607. Sales Person
Problem Summary:
Given a SQL table of sales people orders and companies find all people who never had sales at a company named red
Notes:
Used a bunch of joins and a subquery
Solutions:
1789. Primary Department for Each Employee
Problem Summary:
Given a SQL table of employees in departments find their primary departments based on a flag, or if only one department then the flag isn't given
Notes:
We can basically UNION ALL two separate tables or use an OR with a second query or something
Solutions:
2339. All the Matches of the League
Problem Summary:
Given a SQL table of teams output all possible matches
Notes:
We use CROSS JOIN to make the cartesian product
Solutions:
1965. Employees With Missing Information
Problem Summary:
Given a SQL table of Employees and of Salaries find all employee ids where some data is missing
Notes:
We can use a full outer join and then COALESCE a working id and WHERE when any field is null
Solutions:
1853. Convert Date Format
Problem Summary:
Given a SQL table of dates convert the formatting
Notes:
TO STRING works which takes a date and a format, we need FM to remove spaces because historically there was padded spaces in things: Tuesday···, April··· 12, 2022
Solutions:
1327. List the Products Ordered in a Period
Problem Summary:
Given SQL tables for products and orders get all products ordered in a date range with total units >= 100
Notes:
A mix of SUM, JOIN, and GROUP BY
Solutions:
1294. Weather Type in Each Country
Problem Summary:
Given a SQL table of countries and names and another table of weather on dates find the weather in a certain month for each country
Notes:
We use CASE WHEN to get the weather type then take an AVG and join the two tables
Solutions:
1435. Create a Session Bar Chart
Problem Summary:
Given a SQL table of sessions and durations, output a table of bins and how many sessions in each bin
Notes:
This was tricky, first we need to get all the bins, I used a CTE because if we select directly from the table if there is a bin with 0 it wont show up Then I used another CTE to actually get counts per bin Then a final SELECT + count with a GROUP BY and LEFT JOIN. Remember a selected element in a group must be in the group by or use an aggregator
Solutions:
596. Classes With at Least 5 Students
Problem Summary:
Given a SQL table of courses and students find all courses with >= 5 students
Notes:
GROUP BY and HAVING does it!
Solutions:
89. Gray Code
Problem Summary:
Generate a gray code of length 2^n, n <= 16.
Notes:
Since N is small I think there is some backtracking sequence. I also had a recursive sequence where we generate smaller grey codes and use those but I don't remember how it works. See CSES For the linear version anyway.
Solutions:
Gray Code
Problem Summary:
Generate a gray code of length 2^n
Notes:
The general idea of counting in binary is bad because when we have a carry multiple bits change: 011 -> 100 In gray code we can take a number and xor with that number right shifted. That makes it so adjacent bits that were the same get set to 0, otherwise 1. I think this somehow handles the carry issue but I don't deeply understand it here's 3 techniques from claude: 1. Direct formula — O(2^n) gray(i) = i ^ (i >> 1). No recursion, no state. Just math. 2. Backtracking/DFS — O(n · 2^n) Greedy flip the rightmost valid bit. Never actually backtracks in practice, but the framework is there. 3. Reflected construction (the "DP-ish" one) — O(2^n) This is the original construction Frank Gray used. You build n bits from n-1 bits: Take the Gray code for n-1 Mirror it Prepend 0 to the first half, 1 to the mirrored half n=1: 0, 1 n=2: 00, 01 | 11, 10 (mirror n=1, prepend 0s and 1s) n=3: 000, 001, 011, 010 | 110, 111, 101, 100 pythondef gray(n): if n == 0: return [0] prev = gray(n - 1) return prev + [x | (1 << (n - 1)) for x in reversed(prev)]
Drill Type:
Implementre-implement, also we should know the backtracking idea too maybe implement that
Solutions:
3204. Bitwise User Permissions Analysis
Problem Summary:
Given a SQL table of permissions find the bitwise AND of those available to both anyone and everyone
Notes:
postgresql has bit_and and bit_or
Solutions:
3051. Find Candidates for Data Scientist Position
Problem Summary:
Given a SQL table of candidate skills find all candidates good at python + tableau + postgresql
Notes:
I did an inner query to only keep rows with the right skills and then grabbed the ones HAVING count >= 3, could use skill IN ('Python', ...) also
Solutions:
1484. Group Sold Products By The Date
Problem Summary:
Given a SQL table of products sold on dates, give a table with count of distinct products sold and a concatenated string of all unique products sold, by date
Notes:
Only hard part is putting this in the STRING_AGG: STRING_AGG(DISTINCT product, ',' ORDER BY product)
Solutions:
3246. Premier League Table Ranking
Problem Summary:
Given a SQL table of teams with wins / draws / losses get points per team and their ranking.
Notes:
For points we can do: (wins * 3 + draws) AS points For the ranking we do: RANK() OVER (ORDER BY (wins * 3 + draws) DESC) AS position
Solutions:
2504. Concatenate the Name and the Profession
Problem Summary:
Given a SQL table of people and their professions return concatenated strings for them
Notes:
We can use || to concat strings in postgresql and also LEFT to get the first letter of the profession
Solutions:
C. Restricted Sorting
Problem Summary:
We have an array of length N <= 2e5. For a given K, we call it piggy if we can sort the array in mono-increasing order by: Select two indices i, j such that |a_i - a_j| >= k, and swap them Find the largest piggy integer k or -1 if it does not exist
Notes:
So two numbers can be swapped if they are >= k apart. If the array was already sorted then any K works so it is -1. Take a sorted version of the array and a not sorted version. For each index that mismatches we need to move our number out and put the right number in. To move our number out we could swap it with the min or max (whichever is further). Once the min or max is in place we can swap the min with the max easily. Get our preferred one. Then swap the desired number back in.
Solutions:
B. Seats
Problem Summary:
We have a binary string of length N <= 2e5. Place 1s such that no two 1s are touching, and we cannot place more. Find the minimum # of 1s to do this.
Notes:
I think we could simulate by placing a 1 if the previous number was a 0, unless the next number is a 1. But I ended up doing math on prefix and suffix and gap sizes which I did not do well at.
Solutions:
A. Divisible Permutation
Problem Summary:
Construction a permutation of size N where |p_i - p_i+1| is divisible by i for all i. It always exists.
Notes:
We can basically do this type of thing: 5 6 4 7 3 8 2 9 1 10 5 4 6 3 7 2 8 1 9 I just printed the answer to derive this
Solutions:
E. Count Paths
Problem Summary:
Given a tree of N <= 2e5 vertices every vertex is a color from 1 to N. A simple path is good if it has >= 2 vertices, the ending vertices are the same color, and no other vertex on the path is that color. How many good paths are there?
Notes:
We can answer the question for each node as if we analyze all paths passing through it as the LCA. We small to large aggregate counts of colors. So any cell below us that is our root color and doesn't have any more going up. We also combine paths across children. And we send back up our counter but reset the root node color to 1.
Drill Type:
ImplementRe-solve with C++ DRILL 1: 4/23/26 Was able to cleanly use Info concept for merging, handled & references well, a few snags: -Forgot an edge case, since we initialize heavy to childs[0] I forgot to initialize the result too -I did Info& heavy = childs[0] so when we return heavy at the end we need to return move(heavy) I think -did long long paths = some int * some int, but that evaluates it in ints first, need to do (long long)some int first to avoid overflow -childs.push_back(move(childInfo)) also needed a move here I think, since Info childInfo = self(self, child) is an rvalue, something like that submission url https://codeforces.com/contest/1923/submission/372268605
Solutions:
C. Find B
Problem Summary:
An array A of length M is good if theres another array B of length m where: The sums are the same Every index number is different All numbers are > 0 Given an array C of length N <= 3e5 and Q <= 3e5 queries of [l, r] determine if that subarray is good
Notes:
Given some random array of numbers [1, 2, 4, 3] we could easily squash everything to [7, 1, 1, 1] to always make it good. Any number that was already a 1 has to be incremented to 2, any number above 1 can be dropped down to 1. Prefix query on these.
Solutions:
B. Monsters Attack!
Problem Summary:
We are on a n integer number line with negatives and positives. Monsters are coming from both directions with health points and we can shoot K bullets a second (each decreases a health by 1). Monsters step forward every second, can we survive?
Notes:
The two directions is a trick, flatten it into one direction, then we kind of loop and count
Solutions:
A. Moving Chips
Problem Summary:
We have a ribbon of N <= 50 cells. Each cell has a chip or is empty. In a move we can take a chip and move it to the closest empty cell on the left. Min # of moves to form a connected block of all chips?
Notes:
The trick is if we have some block region like: 1 0 0 1 1 1 0 0 1 To move that group of 111 we actually pick up the rightmost one first each time. Answer ends up being the gaps of 0s in between
Solutions:
D. Slimes
Problem Summary:
We have N <= 3e5 slimes of size <= 1e9. Every second a slime can eat a neighbor slime if its bigger than the neighbor, then it forms a new combined size slime. For each slime, figure out the minimum number of time this one can be eaten by other, or -1 if not possible
Notes:
Any slime next to a bigger neighbor has time = 1. Otherwise we are at a local max like this: bigger than neighbors: _ - _ one smaller neighbor and one equal one _-- equal neighbors: --- We think that some adjacent block of slimes next to us on the left or right would be able to eat us first. A block can eat us if the sum is > our size and there are at least 2 different sizes there (so one can eat another and start the chain) so we can binary search on both sides for the smallest path. Two different elements in a range can be max + min sparse table or we can track the nxt[i] occurence of each element type
Drill Type:
MindsolveRe-read notes
Solutions:
https://codeforces.com/problemset/problem/2094/F
Problem Summary:
We are given N, M, and K. K <= N * M <= 2e5. Output an N * M grid where every number is from 1 to K, they all appear equal number of times, and no two adjacent cells have the same number.
Notes:
Observe if we tile like: 1 2 3 4 1 2 3 4 1 2 . . . We get no repeats, unless the width is divisible by K: 1 2 1 2 1 2 1 2 In that case, we can just shift every other row: 1 2 1 2 2 1 2 1 1 2 1 2 ...
Drill Type:
MindsolveRe-read idea
Solutions:
Number Spiral
Problem Summary:
Given an infinite grid where the cells are labeled in a zigzag pattern compute the number at x, y
Notes:
Basic math
Solutions:
3830. Longest Alternating Subarray After Removing At Most One Element
Problem Summary:
Given an array we can remove one element. Find the maximum subarray sum of an alternating subarray.
Notes:
We can store maxUp and maxDown prefixes and suffixes. Then for each element consider if we remove that. We could also do dp(i, lastRemoved, lastUp, anyRemoved) or something like that but it is 8n memory.
Drill Type:
MindsolveJust quickly re-read the maxUp and maxDown prefix/suffix
Solutions:
3829. Design Ride Sharing System
Problem Summary:
Support add rider, add driver, match earliest two, and cancel rider functions
Notes:
We can use queues, we also track what is in the queue for some other problem requirements
Solutions:
2082. The Number of Rich Customers
Problem Summary:
Given a SQL table find the # of customers with at least one bill > 500
Notes:
We could do a subquery to first get groups, then select the count of those groups. Or just COUNT(DISTINCT ...) Note this was done in mysql as postgresql was not an option
Solutions:
3198. Find Cities in Each State
Problem Summary:
Given a SQL table of states and cities combine cities per state
Notes:
STRING_AGG does this
Solutions:
1565. Unique Orders and Customers Per Month
Problem Summary:
Given a SQL table find unique orders and # of unique customers with invoices > $20 per monthly basis
Notes:
We have to use TO_CHAR to convert annual dates to month buckets. GROUP BY on that as well. Then it's COUNT and COUNT(DISTINCT...).
Solutions:
1777. Product's Price for Each Store
Problem Summary:
Given a SQL table of products and stores reformat the table to have more columns
Notes:
We can use MAX and casing like this: SELECT product_id, MAX(CASE WHEN store = 'store1' THEN price END) AS store1, MAX(CASE WHEN store = 'store2' THEN price END) AS store2, ...
Solutions:
3150. Invalid Tweets II
Problem Summary:
Given a sql table of tweets find invalid ones, length > 140 or more than 3 # or @
Notes:
We can use WHERE and OR. We use LENGTH and regexp_count to count characters.
Solutions:
1587. Bank Account Summary II
Problem Summary:
Given a SQL table of users and transactions find those with total transactions > 10000
Notes:
Just select the users and sum of transactions per group, join the tables, and then use having on another sum to filter for >10000
Solutions:
1179. Reformat Department Table
Problem Summary:
Given a SQL table of revenue per month reformat the table to have each month as a column
Notes:
We can use MAX on the revenue and rename them, like this: SELECT id, MAX(CASE WHEN month = 'Jan' THEN revenue END) AS Jan_Revenue, MAX(CASE WHEN month = 'Feb' THEN revenue END) AS Feb_Revenue, ...
Solutions:
2072. The Winner University
Problem Summary:
Given a SQL table of new york student scores and one of california student scores print the winning university based on which had more students scoring > 90
Notes:
We can do SELECT CASE WHEN ny > ca and then later pull FROM two selected subtables that we name ny and ca.
Solutions:
2377. Sort the Olympic Table
Problem Summary:
Given a sql table of countries with gold/silver/bronze medal counts return them in sorted order of gold -> silver -> bronze
Notes:
We can just chain ORDER BYs
Solutions:
2987. Find Expensive Cities
Problem Summary:
Given a SQL table of home price listings in different cities, find all cities with an avg price above the national avg
Notes:
We can do a subquery where the inner one is just selecting the average from all listings
Solutions:
1741. Find Total Time Spent by Each Employee
Problem Summary:
Given a SQL table of times different employees entered and exited the office each day, return the total office time for each employee for each day
Notes:
SUM the exit-entry times and GROUP BY both day and employee id
Solutions:
2985. Calculate Compressed Mean
Problem Summary:
Given a SQL table of items per order and # of orders compute the average amount of items per order
Notes:
Get the total amount of items ordered and the total amount of orders first, then do a ROUND divsion on the subquery
Solutions:
1571. Warehouse Manager
Problem Summary:
We have a Warehouse SQL table and a Products table and we need to calculate the total volume of products in each warehouse.
Notes:
Use SUM to add up volumes of all products in a given warehouse. GROUP BY is needed since multiple products can exist in a warehouse but we want a per-warehouse report.
Solutions:
1821. Find Customers With Positive Revenue this Year
Problem Summary:
Given a CUSTOMERS sql table with revenue by year we need to find those with positive revenue in 2021
Notes:
Just select + where
Solutions:
242. Valid Anagram
Problem Summary:
Check if two strings are anagrams
Notes:
Two counters are equal or use one counter and decrement in the second string
Solutions:
190. Reverse Bits
Problem Summary:
Reverse bits of a 32 bit signed integer
Notes:
Fun and easy bit problem. We could take the smallest up to largest bits of the input, and apply them to the right edge of the output, or other ways
Drill Type:
ImplementHonestly redo because I think my solution is cleaner than the normal way I might think when reading
Solutions:
3591. Check if Any Element Has Prime Frequency
Problem Summary:
Return true if the frequency of any element is prime
Notes:
standard check primes with a sieve up to max frequency
Solutions:
2239. Find Closest Number to Zero
Problem Summary:
Find the closest number to 0 in an array
Notes:
trivial
Solutions:
3627. Maximum Median Sum of Subsequences of Size 3
Problem Summary:
We have an array with length divisible by 3. Return the maximum sum of medians of groups of 3 elements.
Notes:
Sort. We basically take the 2nd to last, 5th to last, and so on. Proof is we start at the biggest, it cannot be a median but it unlocks one on the left. And so on.
Drill Type:
MindsolveQuick re-read notes
Solutions:
3823. Reverse Letters Then Special Characters in a String
Problem Summary:
Given a string reverse the lowercase and special characters in place.
Notes:
basic string manipulation
Solutions:
3824. Minimum K to Reduce Array Within Limit
Problem Summary:
We have an array of numbers N <= 1e5, A[i] <= 1e5. In one operation we can reduce a number by k. Find the min # of operations K, such that the number of operations to reduce everything to <= 0 is <= k^2 operations.
Notes:
The bigger K is the easier it gets. Binary search on answer and loop through array.
Solutions:
3828. Final Element After Subarray Deletions
Problem Summary:
We have an array of length <= 1e5, A[i] <= 1e5. Alice can remove a subarray. Then bob. And so on. The final score is the last element remaining, what is the max Alice can score?
Notes:
Alice can guarantee the max of front or back. Should she attempt anything else, Bob can remove anything higher than those two.
Solutions:
3827. Count Monobit Integers
Problem Summary:
Find the # of elements from 0...N (N <= 1000) with all bits set.
Notes:
Brute force but could use more advanced methods for bigger N that are log based, or just count the # of bits in the N. Don't forget 0 is a valid number too.
Solutions:
3825. Longest Strictly Increasing Subsequence With Non-Zero Bitwise AND
Problem Summary:
Find the length of the LIS with a bitwise AND > 0
Notes:
For each bit up to log(max), get a new array with elements that have that bit, run the n log n LIS on that n * log n * log(max)
Solutions:
2958. Length of Longest Subarray With at Most K Frequency
Problem Summary:
Find the longest subarray where the frequency of every element is <= k
Notes:
Just use a variable window
Solutions:
2953. Count Complete Substrings
Problem Summary:
We have a string of length <= 1e5 and a k <= n. Find the # of substrings that: -Each character in it occurs k times -The difference between adjacent characters is at most 2
Notes:
If every letter in it appears K times, we can do single letter windows, double letter windows, all the way up to 26 letter windows. For each of those, count good subarrays. Could handle the bad adj difference with a bad count inside the window or just track the furthest right bad pair Have / need trick to make it 26n instead of 26^2 n
Drill Type:
MindsolveRe-read notes on fixed # of window sizes
Solutions:
2524. Maximum Frequency Score of a Subarray
Problem Summary:
We are given an array and k. N <= 1e5, k <= N, A[i] <= 1e6. A frequency score is the sum of distinct values in a subarray raised to the power of their frequencies. Find the max frequency score of a subarray size K
Notes:
We can easily maintain this data with a counter of frequencies and update in a sliding window
Solutions:
1862. Sum of Floored Pairs
Problem Summary:
Find the sum of floor(nums[i] / nums[j]) for all pairs in an array. N, A[i] <= 1e5
Notes:
Each number can only change its floor sum rootN times. We could compute for each number, the left and right boundaries for the rootN quotient blocks, and see how many numbers are in that range with a prefix sum. We have at most 1e5 unique values so if we cache that information per number type we could do root1 + root2 + root3 + ... + rootN We know 1 + 2 + ... + x is x^2 since there are x/2 pairs that sum to x+1. Hmm I don't see a simple math proof for this yet. But that is n * root(max). We could also use harmonic series, for all numbers in the sequence we iterate their multiples and compute the range of numerators that could create this multiple, then use a prefix sum query to count elements in that range, n log n
Drill Type:
ImplementImplement both the n log n and my attempted idea for n root n
Solutions:
1712. Ways to Split Array Into Three Subarrays
Problem Summary:
Find the # of triple-splits of an array where the left subarray sum is <= the middle <= the right.
Notes:
For each left index, binary search on the right for how far we can go with prefix sums. Note for the binary search we need to search for both left and right positions. We can also use two pointers to go from n log n to n.
Drill Type:
MindsolveQuickly re-read two pointers optimization, and the binary search left+right note
Solutions:
410. Split Array Largest Sum
Problem Summary:
Find a partition of k <= 50 sibarrays with a minimum largest sum split. N <= 1000
Notes:
Binary search on answer, try # of cuts, could do DP but way slower
Solutions:
3618. Split Array by Prime Indices
Problem Summary:
Find the difference in sums of elements at prime indices and those at not
Notes:
Just check if a number is prime either with a sieve or on the fly computation
Solutions:
3637. Trionic Array I
Problem Summary:
Find the largest subarray sum that is increasing, then decreasing, then increasing, small N
Notes:
brute force, see part 2 follow up for DP solution
Solutions:
Trionic Array II
Problem Summary:
Find the max subarray sum that is increasing, then decreasing, then increasing
Notes:
Can do dp(i, stage) or state machine dp
Solutions:
M. Triangle Construction
Problem Summary:
We have a regular N <= 2e5 sided polygon. Each side has points on it which divide that side into many equal sized regions. Points per side up to 2e9. Find how many non-degenerative triangles we can place at the same time without overlap.
Notes:
I tried some weird queue simulation thing at worked but it failed on a triangle with points 3,3,3 because it paired up the first 2 sides fully and left the third side alone. If the max points on any side is 1 we can easily pair up triplets so we just get % 3 remainder leftover. If the max side has > 2x the other sides added together, we can always use 2 points at a time from the max, and 1 elsewhere, and our leftover is what is left in the max side. If the max is not 1, we can take the side with the max, pair 2 edge points with the next adjacent edge with a point. This produces no issues as we always have a valid move next (either max is not 1 again, or max is 1 and we can use all but leftovers).
Drill Type:
MindsolveJust re-read notes, this is a lesson in reducing states seamlessly like pair 3 points together and nothing changes (pair adjacent 3 points, won't interfere later).
Solutions:
D. Tandem Repeats?
Problem Summary:
We have a string of length <= N with letters are ?. Find the longest length 2*D, such that the first half equals the second half, ? means we can change a letter.
Notes:
A trivial brute force is check each size, for every size, check each substring. So size 2 does (2 + 2 + 2 + ...) work (n - 2) times. 4 does 4 + 4 + .... I think this ends up being n^3 but I could not technically prove it. Instead we can actually use a sliding window. Because in 1 2 3 4 5 6 7 8 9 10, say we are looking at 1-4 and 5-8. They have some amount of matches (or question marks). As we slide by 1, the matches stay matched up. So we can do a definitely n^2 algorithm.
Drill Type:
MindsolveRe-read notes, refresh idea of this sliding window concept to find the # of differing indices between two windows
Solutions:
D. Problem about GCD
Problem Summary:
We are given L, R, G <= 1e18. Find a pair (A, B) with the largest |A - B| where A and B have a gcd of G, or show impossible.
Notes:
First find the smallest L' >= L divisible by G. Same with R' <= R. At best case this is our answer. If it isn't, we could try (L' + G, R') and (L', R' - G). These terms are basically some coefficient * G and we need the coefficients to be coprimes. Coprimes are not very far (editorial has more details on this with better bounds) so we can test everything. But my simple idea is primes are not very far (prime gaps) and two primes are coprime. So as soon as L'' = some prime * G and R'' = some prime * G they are coprime except for the G. Not the most airtight bound.
Drill Type:
MindsolveRe-read notes
Solutions:
C. Road Optimization
Problem Summary:
We have N <= 500 road signs at positions <= 1e5. We can remove K <= 1e5 road signs. The road signs indicate speed. We drive at that speed until the next sign. Find the minimum travel time.
Notes:
We remove signs in contiguous blocks. dp(i, removalsLeft) and we for loop on a block for n^3. CHT supposedly can do n^2 log n.
Solutions:
D. Mysterious Present
Problem Summary:
We have N <= 5000 envelopes of size WxH, W,H <= 1e6. Find the longest chain of nested cards and print it out. We cannot rotate cards.
Notes:
Sort cards by increasing W and decreasing H. Find the LIS. Reconstruct. N log N doable too.
Drill Type:
MindsolveRe-glance at construction code, refresh the sort idea
Solutions:
D. Price Tags
Problem Summary:
We have N <= 2e5 priced items of prices <= 2e5. We must put the items on sale. We choose an X >= 2 and each price becomes ceil(oldPrice / X). But we have to print new price tags, though we can re-use old ones if we have them. Printing a tag costs Y <= 1e9. Our profit is the sum of the new prices minus the printing cost. Find the highest profit. Test cases <= 10.
Notes:
Alright so first I tried considering each X. We know a price Z will have at most 2 * rootZ unique ceiling divisions. So worst case for N different prices we do root(1) + root(2) + ... root(N) work which is average work of rootN per all N times, so N root N work. So in theory enumerating these should be sufficient. I iterated on numbers and for each number found their 2 * root(number) unique ceiling quotients. Then built a map of ceiling quotient -> interesting numbers. This took n root n space. Then I looped on each X, inside I looped on the interesting numbers, updating the amount of tags needed and total price. This ended up MLE though from N root N. I then used GPT to build some way to compute the interesting numbers on the fly but it TLEd. So then the real solution is instead of "loop over X, inside loop over interesting values for X" it is "loop over X, loop over new price possibilities". The new price possibilities work amortizes to N log N like harmonic series. Like if X=1 we do X work inside. X=2 we do X/2 work inside. So X + X/2 + X/3 + X/N For a given new price, we need to see the original prices that mapped to this. Imagine X=10 and we have a new price ceiling target of 30. L=291 as ceil(291/10) = 30. R=300. We can find how many original tags were in this range using a prefix sum range query. We see how many new tags of 30 we need to make based on the existing count and our prefix query.
Drill Type:
MindsolveRe-read notes, re-understand this simple L and R setup, takeaway is to not tunnel vision on the more complex N root N idea
Solutions:
B. Long Legs
Problem Summary:
We are at 0,0 and have leg length 1. We can do these: -Jump to x+leg length,y -Jump to x, y+leg length -Increase length length by 1 Find the minimum # of moves to reach (a, b). a, b <= 1e9
Notes:
I had a great observation here to simplify. Say we grow to size K then jump to the corresponding X and Y coordinates (these can be solved independently). If we overshoot, it is okay, as we previously had a smaller length length we could have used. So for each length we can just find the ceiling of the distance over our length and it takes that many jumps. I had an intuition we only need to go up to root(max(a,b)) leg lengths. Say the distance is 1e9 and we grow to size 1e6 then we do 1e3 jumps. That's worse than growing to size root(1e9) and doing root(1e9) jumps sort of idea.
Drill Type:
MindsolveRe-read notes about clean simplification to implement
Solutions:
G2. Magic Triples (Hard Version)
Problem Summary:
We have N <= 2e5 numbers <= 1e9. Find the # of index triplets i,j,k where a_i * some integer = a_j and a_j * that integer = a_k Note ordered pairs are different, so [1, 1, 1] has 6 triplets. And [8, 2, 4] has 1 triplet.
Notes:
Here is how we do G1 which had numbers <= 1e6: Okay first any triplet of the same number can be handled separately. Now we sort the array and for a given value we can loop over all its factors and check the left and right side frequency counters. We could build all factors from 1 to 1e6 in M log M time then our loop is N log M time but I MLEd but I think C++ might have worked. Instead I found a way to quickly factorize numbers on the fly without storing them all in advance by generating an SPF array and prime factorizing then producing those factors on the fly. Also note I had an issue using an array frequency tracker from 1 to 1e6 because I would create that per test, so we needed a python counter instead. Now I tried these things for G2: -Pollard rho to fast factorize each number on the fly, wasn't fast enough, I don't have good understanding of complexities -Iterating all ~3400 primes for each number to prime factorize then generate numbers, too slow especially if they spam numbers which are the products of 2 high primes we would loop through nearly all 3400 every time Solution is if a number is <= 1e6 we can just loop on its divisors, thats sort of like M log M harmonic series type work. If it is above 1e6, not every divisor matters, because then the bigger term would be too big. So we are bounded up to 1000 options which we could manually loop through. Note that for <= 1e6 I couldn't do trial division even though it is also 1000 operations but maybe I could constant optimize Also annoying thing in this question was memory limit so to factorize I needed spf array not the n log n divisor sieve Takeaway here is don't get too obsessed with the prime data structures, this was more of one of those "square root decomp" esque work ideas. Though maybe there is a way to use pollard rho here not sure
Drill Type:
MindsolveJust re-read notes
Solutions:
F. Gardening Friends
Problem Summary:
We have a tree of size <= 2e5 rooted at 1. Each edge in the tree has weight K <= 1e9. At a given root we find the maximum distance to another node. This is our profit. We can adjust the root to an adjacent node for cost C <= 1e9. Find the maximum profit overall.
Notes:
Tree reroot DP. We need to reroot like this: -Record the best 2 depths to go down through different children in dfs1 -In dfs2 we iterative over children, they can either go down through themselves, or go up to our node then back down through a different node (we check using the 2 distances), or go up and then up again Find the cost based on distance from root 1
Drill Type:
MindsolveI won't make you re-implement this but do re-read the code because implementation of dfs2 is a bit tricky. I should have a tree distances reroot DP somewhere else so no need to redo here. But also note that we can store the furthest node itself for each node, not just the distance. I made 2 templates for C++ and python for tree distances from this too.
Solutions:
G1. Magic Triples (Easy Version)
Problem Summary:
We have N <= 2e5 numbers <= 1e6. Find the # of index triplets i,j,k where a_i * some integer = a_j and a_j * that integer = a_k Note ordered pairs are different, so [1, 1, 1] has 6 triplets. And [8, 2, 4] has 1 triplet.
Notes:
Okay first any triplet of the same number can be handled separately. Now we sort the array and for a given value we can loop over all its factors and check the left and right side frequency counters. We could build all factors from 1 to 1e6 in M log M time then our loop is N log M time but I MLEd but I think C++ might have worked. Instead I found a way to quickly factorize numbers on the fly without storing them all in advance by generating an SPF array and prime factorizing then producing those factors on the fly. Also note I had an issue using an array frequency tracker from 1 to 1e6 because I would create that per test, so we needed a python counter instead.
Drill Type:
MindsolveRe-read code for generating factors on the fly as we prime factorize with the spf array
Solutions:
D. Problem with Random Tests
Problem Summary:
We are given a randomized binary string of length N <= 1e6. Note the input is randomized at the time the tests are ran, so they cannot be adversarial. "Problem with random tests." We can select two substrings (can be the same, different, overlap) and OR them together. Find the max OR and return it as a substring with no leading 0s.
Notes:
Okay one trap here I picked up somewhat on is to relax conditions. For instance obviously at the first 1 that occurs, we want that entire suffix substring. But also note taking the empty 0s on the left does not harm anything. So really we can take the entire s as the first string. And same for the second string, we could consider any second string of some specific length to set that 1 bit, but we could also note that any full prefix can do no worse than a given substring, so both strings taken can be prefixes. This can simplify our reasoning and code maybe. We have a string like 111100101 We need some string that can activate that 0 bit. We could try all substrings of that required length but it is hard to determine which is best (maybe FFT?) Instead note that only a few prefixes can even reach that 0 bit. For example if the string is: 11011111111111 There's only like 2 prefixes that can even reach it. And we expect that first 0 to occur early because it is a randomized input. So we can brute force test them.
Drill Type:
MindsolveRe-read notes
Solutions:
E. Permutation Game
Problem Summary:
We have a permutation of size <= 5e5 and two players. All numbers are colored colored red. On my turn I can: -Re-permute all blue colors -Change a red into a blue -Skip action Player 1 wants an ascending array player 2 wants a descending array. Print the result.
Notes:
Note that I shouldn't permute unless I'm about to win, because for me to win I need all my mismatched numbers to be blue. Permuting doesn't do anything because I still need to permute again later. So I want to color my mismatched numbers. # v v v descend # 1 5 6 3 2 4 # ^ ^ ^ ^ ^ ascend # Always color tiles your opponent does not have I should color my exclusive cells first, then the shared ones. If there's only shared cells left to color it is a deadlock. I simulated it but we can just use some math observation.
Solutions:
D. Sum of XOR Functions
Problem Summary:
Given an array of length <= 3e5 with numbers <= 1e9, find the sum of all subarray XORs * their lengths.
Notes:
Solve bit by bit. So now our array is 1s and 0s. If a subarray has an odd amount of bits, its XOR is 1 and so the contribution for that subarray is just its length. Therefore we need the sum of lengths of all subarrays with an odd number of bits. At first I did this with a cursed top down dp(index, isIntervalOpen, currentParity) which returned both the sum of all subarray lengths but also the number of subarrays. This barely passed in time when using a static array. Then I did it more of like a prefix style. We iterate on each bit tracking sumOddBits, sumEvenBits, countOddBits, countEvenBits. We can also do kind of a lop off style which is related.
Drill Type:
MindsolveRe-read notes and code, basically 3 methods but the third one I didn't fully look into
Solutions:
C. Bargain
Problem Summary:
We have a digit string of length 1e5. We can remove any substring from it. That gap is then removed and the numbers around it get squished together. So 123 and we cut out 2 becomes 13. Find the sum of all remaining numbers.
Notes:
We will add up each digits contribution independently. For that digit, say in 12345, looking at 3. This contributes 300 normally. There are prefix substrings cut off that change nothing. We can easily compute how many. If we cut off ones on the right we could contribute 300, 30, or 3, with varying quantities. Look at the 4. We can cut off a 5 on the right, so there is 1 way to get a 4 contribution of length one. Ignore the 4 coefficient for now. 1*10^0 At the 3, we can cut off 2 different substrings of length 2 to get a length 2 contribution (10), and 1 substring to get a length 1. 1 * 10^0 + 2 * 10^1 At the 2, we have: 1 * 10^0 + 2 * 10^1 + 3 * 10^2. We can easily precompute all of these and then add in the digit contribution coefficient after.
Drill Type:
MindsolveRe-read solution and code
Solutions:
D. Umka and a Long Flight
Problem Summary:
Call a fibonacci rectangle of order N an f(n) * f(n+1) grid. Give N <= 44 and coordinates for a marked cell in this fib rectangle, can we split up our rectangle into smaller squares, at most two with the same side length?
Notes:
I realized That a fibonacci rectangle is the sum of the smaller fib sqaures tiled together. F0 and F1 are both 1 so these are the squares that get the same side length. When we have say an 8x13 it means we placed a 8x8 square and then had an 8x5 region which is another fib rectangle one order smaller which is the sum of more squares. If that 1x1 cell must go into the cut off square portion we cannot do it. I used recursion.
Solutions:
E. Cells Arrangement
Problem Summary:
Given an N <= 1e3 we have an NxN grid. We can place N tiles. Let S be the number of distinct pair manhattan distances between tiles. Find the max X and construct a grid.
Notes:
Theme of constructive: build off of smaller constructions. Also the max possible distance is 2xN - 2. Brute force up to N=4. If we can get something like this which has all possible distances from 0 to 2N-2 (this 3x3 doesn't, just an example, but we can at N=4) X X o o o o o o X Then we add a new layer, if we place it at the bottom right, we add both the new max and new max - 1 distances.
Solutions:
D. Shocking Arrangement
Problem Summary:
We have an array of length <= 3e5 with numbers >= -1e9 and <= 1e9. The sum is 0. Construct a permutation of it where the max absolute value of any subarray is < max element - min element.
Notes:
Since the sum is 0 we either have all 0s or at least one negative. All 0s is impossible. At least one negative means max - min actually helps us. It's basically saying we can lay out elements but if a contiguous subarray ever exceeds that max and min combined we fail. We need to teeter up and down and stay in range. My theory and solution was to keep adding the largest possible number we can, maintaining a max prefix sum. If we get too close the largest number would end up being a negative number. I didn't have an airtight proof but it ACd and I think I could prove it if I thought more. Some sort of packing problem esque behavior. The editorial had a better idea: If our current sum is positive we have at least one negative element, so palce the negative. If it is negative, we have at least one positive, place that. We can never exceed because the buffer gives us room.
Drill Type:
MindsolveRe-read notes
Solutions:
G. Short Task
Problem Summary:
given a number C <= 1e7, find the smallest n where d(n) (sum of divisors) = C. We have 1e4 tests so it needs to be fast.
Notes:
First note we can easily get all divisors for 1...C in C log C time with harmonic series, sum them up, and for each sum find its smaller number that attained it. This is C log C which is too slow given the C size. So anything enumerating divisors is too slow. We can enumerate prime factors because that ends up being C log log C which is fast enough. If we could prime factorize everything and somehow use those to find the sum of divisors, we could solve the question. Again remember we cannot take the prime factors and generate all factors as that ends up being C log C time basically like harmonic series. We build an SPF array in C log log C or even just C time. We prime factorize all numbers. There are C log log C prime factors so it is safe to loop over each prime factor (even with multiplicity). Imagine we have a number that is p1^a + p2^b + p3^c and we wish to compute its sum of factors. Any factor selects 0...a from p1, times 0...b from p2, times 0...c from p3. So the sum of factors are like (p1^0 * p2^0 * p3^0) + (p1^1 + p2^0 + p3^0) + ... (p1^a + p2^b + p3^c). if we said: X = {p1^0, p1^1, ... p1^a} Y = {p2^0, p2^1, ... p2^b} Z = {p3^0, p3^1, ... p3^z} Then X * Y * Z is a sum of every possible factor uniquely. So we can enumerate the prime factors and compute X and Y and Z and multiply them. In my code, I had to do this while running the spf to generate the prime factors, to keep it fast enough. Computing all the primes and exponents up front and pushing these pairs into a vector, and then doing X * Y * Z after, was too slow. Another method: d(n) = d(a) * d(b) if gcd(a, b) = 1, apparently. So we can build up factorSum[x] as a dp array. To solve for X we find the SPF of it and how many times it appears. That is one factor, call it p^e. The other factor is X/(p^e). These are coprime. We can then multiply those two to get the new DP value. Or if a number is just a single prime factor with exponents then we can compute it manually.
Drill Type:
ImplementRe-read notes fully to understand complexity more deeply, and re-solve with spf approach and math
Solutions:
G. Mukhammadali and the Smooth Array
Problem Summary:
We have N <= 8000 numbers and we want them to be non-decreasing. We can change a_i to any number for c_i (<=1e9 cost). What is the minimum cost to fix the array?
Notes:
My idea: We only would change numbers to at most the 8000 unique values so store dp[number] -> min cost to end at that number and loop on each index and each previous number type. This TLEs unless you move the hashmap lookup outside the hot path. n^2 We can also do this weird idea: -At an index we can keep the value for all previous values <= current value. Range query for the min cost for all things in some range(0, ourValue) using a seg tree. -We can change this value to any number for c_i and add the previous best dp value for that number type. So we need a lazy range add. So n log n lazy seg tree dp. Editorial: -We can keep some non-decreasing subsequence and everything else must change. Find the max weight non-decreasing subsequence using normal n^2 dp (max weight ending at each index i before us). Or use n log n style lis too.
Drill Type:
MindsolveReread all the options
Solutions:
G. Paths in a Tree
Problem Summary:
Interactive problem. We are given N nodes in a tree N <= 2e5. There are hidden nodes X and Y (can be the same). We ask queries A,B and we are told if the path A<>B has any nodes in common with the path X<>Y. Locate a node on the path in floor(n/2) + 1 queries.
Notes:
I did a postorder DFS. If a node has an odd amount of children I pair one child with the node. If we hit, we query a singleton. If we miss, we pair up the other children two at a time. If we have even children, query two children together. If a hit we query two singletons. Otherwise iterate the other children 2 at a time again. Edge case with 3 nodes makes things weird, we cannot query the two children together as we would use 3 operations. We need to query 2 singletons separately (same with if we are just left with 3 nodes at the end in the form a node + 2 children). A bit messy code. The editorial uses some weird inorder version like this: 1 2 3 4 5 query 1-2 first if no hit, query 3-4, like that Not really sure how the inorder works
Solutions:
F. Pizza Delivery
Problem Summary:
We have N <= 2e5 points (x, y) <= 1e9. We start at Ax and Ay and need to visit all the other points. We can only move up, right, or down. It is guaranteed we can visit all other points. Min distance to travel?
Notes:
Enumerate X left to right. Maintain a dpUp and dpDown for the minimum distance to reach the previous X value at the top and the bottom.
Solutions:
E. Product Queries
Problem Summary:
We have N <= 3e5 numbers <= N. For each index i=1 to N, find the minimum # of values to multiply to form i, or -1 if not doable.
Notes:
Solve in order 1, 2, 3, ... N. We can factorize each number and use dp on the two values. This is N root N. We can generate divisors in advance from 1...N which is now N log N harmonic series. Or even use the advanced O(divisors) method. I think RJ did a push DP too instead of dividing by divisors (but still used a harmonic series theme)
Drill Type:
MindsolveRefresh harmonic idea as I missed it at first
Solutions:
D. Monster Game
Problem Summary:
We have N <= 2e5 monsters. We have N swords of strength <= 1e9. And N monsters with health <= N. Each sword breaks after 1 hit. A monster with health Y dies in Y sword strikes. We can choose any level X and sword < X is instantly useless. But our score multiples by X (score is # of monsters killed). We must kill monsters in order. Max score?
Notes:
I just added interesting values (All monster-1, monster, monster+1) and for each one found out how many swords became useless. Now I binary search for the longest prefix sum of monsters we can kill. I'm sure we can do fewer interesting values to consider or maybe some other loop / sorting solutions.
Solutions:
C. Replace and Sum
Problem Summary:
We have two arrays of size <= 2e5 and Q queries <= 2e5. Each query has [l, r]. Also we can do these operations unlimited times before the queries: Replace A[i] with A[i + 1] Replace A[i] with B[i] For each query find the maximum sum in A
Notes:
Just loop backwards to update A[i], then answer the queries with a prefix range sum
Solutions:
B. Reverse a Permutation
Problem Summary:
We have a permutation of size N <= 2e5. We can reverse a subarray. Find the lexicographical maximum we can make.
Notes:
We want the max element at the leftmost position. If it is, we want the second max at the second position, etc
Solutions:
A. DBMB and the Array
Problem Summary:
Given an array we can change any number by +X unlimited times. Can we make the sum equal to S?
Notes:
Just math
Solutions:
3820. Pythagorean Distance Nodes in a Tree
Problem Summary:
Given N <= 1e5 nodes in a tree, define dx dy and dz as the distances from three given nodes, X, Y, and Z. A pythagorean triplet is one where A^2 + B^2 = C^2. Find how many nodes have dx dy and dz form this triplet.
Notes:
We need to know the distance from each node to x y and z. We can do multi-source bfs (linear), jump tables, or even sparse table lca euler tour distance stuff but I don't tag those since usually lifting is fine
Solutions:
3819. Rotate Non Negative Elements
Problem Summary:
We have an array of integers. Rotate all the non-negative elements left by K and return the final array
Notes:
I just put all the non negatives in a deque and manually rotated, remember to do K = len(negs) % K, we could also not use a deque, but deque is the key to a clean implementation
Solutions:
3818. Minimum Prefix Removal to Make Array Strictly Increasing
Problem Summary:
Find the smallest prefix we can remove to make an array strictly increasing
Notes:
Keep the largest increasing suffix, just loop backwards
Solutions:
3821. Find Nth Smallest Integer With K One Bits
Problem Summary:
Find the Nth number with exactly K bits. K <= 50. N <= 2^50. Guaranteed the answer is < 2^50 (as per constraint).
Notes:
We can binary search for some value X and see how many numbers <= X have exactly K one bits with dp(i, tight, oneBits). This was tight and needed C++ to pass and I also didn't allocate 2x memory for tight. Another solution is math based, we start from a max set bit, if this bit can be a 0 (N numbers < than this exist with k bits set) we keep it as a 0.
Drill Type:
ImplementImplement C++ digit dp version with no tight caching Re-read notes for math combinatorics solution
Solutions:
C. Purification
Problem Summary:
We have an N x N grid (N <= 100) of cells. We can purify a cell which purifies the entire row and column. But some cells cannot be directly purified. Construct a set of minimum cells we need to purify to cleanse the whole grid, or show impossible.
Notes:
Obviously the minimum is N which is just fill every column or every row. If we can do neither then one cell is un-purifiable.
Drill Type:
Mindsolverefresh idea about only needing to put in all rows or all columns, not all diagonals
Solutions:
Permutation Prime Sums
Problem Summary:
GivenN <= 1e5, find two permutations of size N where every pair sum (A[i] + B[i]) is prime or show impossible.
Notes:
Take N, say 5, find the next biggest prime, 7. Now we can pair 5+2 4+3 3+4 2+5. 5 4 3 2 2 3 4 6 So we solve down to 2. New N is 1. Repeat. Next biggest prime is always not much bigger. As long as it is <= 2N it works which it always should be.
Drill Type:
MindsolveReview the concepts of constructive questions here: -can we solve in blocks? -print answers and look for a pattern -what if every pair adds to X? etc
Solutions:
D. Maximum Sum on Even Positions
Problem Summary:
We have an array of size <= 2e5 with elements <= 1e9. We can reverse some subarray l...r. Maximize the sum of even indices after this.
Notes:
It's dp. We basically want to maximize some oddIndex>evenIndex sum surplus for some subarray type of thing, because then we reverse that. It's like Kadane's. But honestly I found my idea easier to understand. We have indices say 0, 1, 2, 3, 4, 5 We don't want to falsely claim we can select some odd-index index range like 1-3 and add on the odd indices there, because odd-odd causes no swaps to actually happen. We could extend the window one to the left or right but then we need to forfeit the even number we extend to. For even-even index ranges we can always flip those and claim the odds inside I think by just dropping one of the even endpoints off but it doesn't really matter. Anyway I did a dp state machine with a bunch of states, notOpen, openStartedOnEvenIndex, openStartedOnOddIndex, closed, which I felt was easier than these weird alternating sum kadane's ideas
Drill Type:
MindsolveReview my notes and code
Solutions:
F. Tree, TREE!!!
Problem Summary:
We have N <= 2e5 nodes. And K <= N. Given a set of K distinct nodes, they have some LCA. Let S_r be the set of distinct possible LCAs when the tree is rooted under r. Find |S_1| + |S_2| + ...
Notes:
For a node to be an LCA here it just means the subtree must be size >= K (necessary + sufficient logic). We can easily solve this for root 1. Find the # of subtrees with size >= K. We can dfs over a child node and update sizes. We lose the root which had subtree size N but gain a new root of size N (no change there). But If we reroot from 1->2 we lose a subtreeSize for the subtree at 2 and we gain N - 2 for the new child that is 1 (basically this is rerooting described poorly). We can bookkeep the answers and then add to our result. I used a multiset-esque thing in my code but this actually isn't needed. Also make sure to undo the changes after we finish that dfs. However there is another version too using contribution technique: We want to know for a given node X, how many roots can this node have a subtree of size >= K. First root the tree at 1. Any node above X as a root would clearly keep the subtree size of X the same. This is O(1) math to add those up. But nodes in the subtree of X, as a root, would change the subtree of X differently. Consider: 1 2 3 4 5 6 7 8 9 10 11 The subtree of node 3 is 7. If 10 is the root we keep {1, 2, 3, 4, 5, 6, 8, 9} in the subtree which is size 8. We look at the DIRECT child of 3 along the path towards 10, which is 7. Everything in that subtree gets excluded, everything else becomes part of 3s new subtree. So we iterate over all direct children for a node and figure out how many nodes are in THAT childs subtree and use math to answer that.
Drill Type:
MindsolveRe-read the second version without rerooting, remember my reroot can be done without a multiset, and we need to undo things after the reroot
Solutions:
C. Beautiful Sequence
Problem Summary:
We have an array of size N <= 2e5 consisting of 1s 2s and 3s. We need to find the # of subsequences of the form 1 [222] 3 (any number of 2s, at least 1).
Notes:
We can use dp[index][prevTaken]. If prevTaken is 0 we can take a 1. If prevTaken is 1 we can take a 2. If prev is 2 we can take a 2 or 3. We can also skip a number. Could use a state machine esque solution too.
Solutions:
B. Set of Strangers
Problem Summary:
We have a N<M (N,M<=700) grid of colors. We can choose any subset of colors that are all the same color, and no two orthogonally touch, and change them all to some color. Minimum # of colors to equalize the grid?
Notes:
Every unique color type takes at most 2 operations. If there is a color type that needs two operations we can also use that as our target color.
Solutions:
A. Was there an Array?
Problem Summary:
We have some hidden array A and a new array B of size A - 2. B[i] is 1 if A[i-1] = A[i+1], otherwise 0. Given a B, was there a valid A?
Notes:
if B = [1, 0, 1] that is bad because there is a contradiction, I didn't airtight validate this but it was simple
Solutions:
A. Candies for Nephews
Problem Summary:
We have N <= 100 candies and three nephews. How many candies must we gain to give each child an equal amount?
Notes:
Just remainder 3 math
Solutions:
B. Deck of Cards
Problem Summary:
We have n <= 2e5 cards. We will remove some top cards, some bottom, or remove either. The cards are in order 1 to N. For each card output if it must have been removed, must be in the deck, or could be either.
Notes:
A card must be removed if it was forcibly removed from the top or bottom. If the number of removals include optional ones = the size of the deck too. A card must be in the deck if we cannot reach it from the top or bottom with all optional removals. Otherwise we can construct a pattern such that the card was maybe not removed.
Solutions:
C. Monocarp's String
Problem Summary:
We have a string of length <= 2e5 with a's and b's. We want to remove the minimum length substring to make remaining a's = b's. Output the minimum length or show impossible.
Notes:
It is lop off technique but a bit cooler. It's sort of inverted. We get the initial surplus and we need to remove that. Just review code.
Drill Type:
Mindsolvere-read notes + review
Solutions:
D. Inversion Value of a Permutation
Problem Summary:
We have N <= 30 and need to construct a permutation of size N with exactly K <= n*(n-1)/2 subarrays of length 2 or more that contain an inversion. Do so or show impossible.
Notes:
This is so hard. Instead of constructing subarrays with inversions construct ones without inversions which are ascending arrays. We have dp(n, noInversionSubarraysToConstruct). We can try placing some ascending subarray and then recursing to a smaller value. If that one works we set choice[state] -> size placed. I had a weird base case where noInversionSubarraysToConstruct = 0 means we place a DESCENDING subarray unlike the others. Had to handle this super weird by marking that state as special in the code. The construction will place side by side increasing subarrays where all prior elements are greater than all next elements to prevent any new noInversionSubarrays. Probably an easier base case but I struggled so hard with this...
Drill Type:
ImplementResolve this it is cursed
Solutions:
C1. XOR Convenience (Easy Version)
Problem Summary:
We are given an N <= 2e5. We need to construct a permutation of size N (1...N) where every 2 <= i <= n - 1 has a j >= i such that P[i] ^ P[j] = i (1-indexed)
Notes:
First print out brute force combinations for small N and notice all N have some sequences ending in 1. Try constructing sequences where the last digit is 1. Also the second to last digit is therefore forced. For the third to last digit we have two options but this becomes complex, see if we can just use the 1 for everything. We are basically saying we need to form 2...N-1 after xor-ing some range all with 1s. I think we could even test this construction at this point for n <= 2e5 and see it always works. But obviously there are no duplicates because the mapping is BIJECTIVE. If all the outputs post XOR are different then all the inputs are different. And the inputs are bounded by 1...N trivially since XOR changes a number by at most 1. Once we place that single 1 on the right and we want to create 2...N-1 post XOR, and we have numbers left 2...N, of course it is doable. Each input number produces 1 above or 1 below. 2 -> 3 3 -> 2 4 -> 5 5 -> 4 6 -> 7 7 -> 6 Obviously any number X ^ Y is going to produce some bijection for a fixed Y because it just forms pairs. X ^ Y = Z. Z ^ Y = X. The first digit that gets placed can just be the leftover. Generally need to think about this more a bit of a fucky problem
Drill Type:
MindsolveJust re-read the whole thing
Solutions:
Nim Game I
Problem Summary:
We have N <= 2e5 piles of stones <= 1e9. We can remove 1 or more stones from a single pile on our turn. Last to remove a stone wins. Who wins?
Notes:
This is a really hard XOR observation. For games if we are in a winning state we must be able to force the opponent into a losing state. If we are in a losing state, no matter what, opponent enters a winning state. Read the github notes to see the proof. Claude thought also: Right, let me make it concrete. Say your piles are [3, 5, 6]. XOR is 3 ^ 5 ^ 6 = 0. That's a losing position for the player to move. Any move changes exactly one value, so the XOR goes from 0 to old ^ new, which is nonzero since old ≠ new. That direction is straightforward. The other direction is the clever part. Say piles are [3, 5, 4]. XOR is 3 ^ 5 ^ 4 = 2 (binary 010). You want to find a single pile to reduce so that the total XOR becomes 0. The trick: look at the highest set bit of the XOR result (bit 1 in this case). At least one pile must have that bit set — otherwise it couldn't appear in the XOR. Here, pile 3 (011) and pile 6 (110) both have bit 1 set. Pick one, say pile 3. Now XOR that pile with the total XOR: 3 ^ 2 = 1. This is less than 3 (guaranteed, because you're flipping off the highest bit of the XOR, which was set in this pile). So reducing pile 3 down to 1 is a legal move — you're removing 2 stones. After that move, piles are [1, 5, 4], and 1 ^ 5 ^ 4 = 0. You've zeroed it out in one move. The key insight is that p ^ totalXOR < p is always true for at least one pile p, because whatever the highest bit of totalXOR is, some pile must have contributed it — and XORing it knocks that bit off, making the value smaller. That gives you a valid move (reducing, not increasing) that zeros out the total XOR.
Drill Type:
MindsolveRe-read the code and reasoning carefully
Solutions:
B. The Curse of the Frog
Problem Summary:
This problem was confusingly worded. We are at position = 0 and want to reach X <= 1e18. We have N <= 1e5 types of jumps [A, B, C]. Where A is how far forward we can jump (we can pick any size <= A). C is a curse, we first move backwards by C, but only every B-th jump, repeating. So [2, 4, 3] means we jump forwards by up to 2, but the 4th, 8th, etc jumps we first fall back 3 then jump forward 2. Min number of fallbacks we endure to reach X?
Notes:
First move forward with every jump until right before the fallback. If we are >= X we win with no fallbacks. Otherwise we will use at most one jump type, just do math on them. However note here to NOT use math.ceil because it has precision issues. Like 5.03 might imply 6 jumps but it is better to use mod math and remainders.
Drill Type:
MindsolveRefresh the idea of not using math.ceil on float division
Solutions:
A. Table with Numbers
Problem Summary:
We have an H x L table (H, L <= 1000). We have N <= 100 numbers <= 1000. We can pick two numbers and form coordinates (a, b). If that is on the table we increment by 1. What is the max sum we can make the table?
Notes:
X pairs are doable if there are X numbers <= min(H, L) and 2X numbers <= max(H, L).
Solutions:
C. Karen and Supermarket
Problem Summary:
We have a tree where each node has a price or a coupon price. We can only buy a node at the cheaper coupon price if all ancestors were bought at the coupon price. We have N <= 5000 nodes and a budget B <= 1e9. Prices are <= 1e9. What is the most # of nodes we can buy?
Notes:
First note we cannot have dp[budgetLeft] -> most nodes because the budget is big. So we do dp[nodes] -> min spent like the knapsack DP tricks and then find the most nodes with a min spent <= B. Establish a DP state dp[node][attainedNodesInThisSubtree] -> min cost to get that many nodes in the subtree of node. Then obviously our answer for the question is max dp[1][x] over all x <= N. To merge children, we should look at taking 0 from the left child, 1 from the left, and so on, with 0 from the right, 1 from the right, and so on. However this works for the no coupon situation. We actually have two states. coupon[node][attained] and noCoupon[node][attained]. Coupon refers to we MUST coupon the root and no coupon means we must not. Note these states are easier to work with "action states" rather than "permission states" like "can coupon at the root but we don't have to". The latter is complicated because we would need to try couponing the root and then iterating all children with the ability to coupon them but don't need to, and also try not couponing the root and iterating over all noCoupon children. It should be doable but seems more complex. The action state is fine because either we are going to coupon the node of course or not. And it is implied if we coupon the node we couponed all above it, but that doesn't matter from our DP perspective because that is upstream. To handle the must coupon root we need to see the best of a no coupon child and a coupon child, we can pick the best for each one. We should not try to merge first with the no coupon child then merge again with the coupon child since that could conflict as we re-use things from children. We should first minimize the coupon child and no coupon child ahead of time. The base case for coupon at a leaf is coupon[leaf][0] = INF also since we cannot coupon a node and take 0 from that subtree. It looks like we do n^3 work. Because every node is considered a child once, and each of those times we merge n * n so we get n^3. But that is n^3 only if we loop over all of n for each child. If we loop over subtree sizes it is n^2. Imagine two nodes in the tree, they get combined / accumulated only once, at their LCA. Imagine each operation in a merge is like taking up to L from left child and up to R from right child and it takes L*R time. This is sort of like picking two nodes and seeing they only get combined once. So it ends up being n^2. Editorial had some heavy child idea not sure if that is ever useful or improves complexity. Also note we probably don't need a leaf base case separately, we could just have our base case implicit by the merging logic / "vacuous" state
Drill Type:
ImplementRe-implement fully + read notes
Solutions:
E. Sending a Sequence Over the Network
Problem Summary:
We have a sequence of numbers. Length <= 2e5, A[i] <= 1e9. We can take some sequence and split it into segments and insert the length of each segment to the left or right. For instance: [1, 2] -> [1, 1] [1, 2] (add 1 to either side of 1, 1 to left of 2) [1, 2] -> [1, 2, 2] (add 2 to right) [1, 2] -> [1, 1] [2, 1] (add 1 to right of each) etc Could our original sequence have been produced from some other sequence after following these operations?
Notes:
DP[i] tells us if s[i:] is doable. By default N is doable. Iterate backwards. If we have some number X look ahead X spots. If that is doable, then DP[X] is doable. If DP[X+1] is doable then backwards X characters is doable too.
Drill Type:
MindsolveQuickly gloss over notes
Solutions:
B. Password
Problem Summary:
Find the longest string that is a prefix, suffix, and a non prefix/suffix substring of some string s. |s| <= 1e6
Notes:
I computed z-function. For every suffix, if it matches the prefix, and there is a count of 2 or more z-values >= that length, we can use this substring. We can also use kmp somehow (I don't know it) or binary search for the longest length with rolling hash and scan the entire string
Drill Type:
MindsolveQuickly gloss over notes
Solutions:
Bit Inversions
Problem Summary:
We have a binary string. Support point updates and report the longest substring of all the same bit.
Notes:
We can use a seg tree, node stores: Max consecutive block in range (of any number type) Max consecutive prefix Max consecutive suffix Width (to make things easy to merge, not needed) Leftmost value (could bookkeep this elsewhere) Rightmost value (same) We could also use a sorted list of ranges and a second sorted list of sizes. When we flip a bit we split off the range, and if it was an ending bit we merge with its adjacent range. GPT had some implementation: map<int,int> runs; // start -> end multiset<int> lens; string s; void eraseRun(int l, int r) { lens.erase(lens.find(r - l + 1)); runs.erase(l); } void addRun(int l, int r) { runs[l] = r; lens.insert(r - l + 1); } void flipPos(int pos) { auto it = runs.upper_bound(pos); --it; int l = it->first, r = it->second; eraseRun(l, r); char oldBit = s[pos]; s[pos] = (s[pos] == '0' ? '1' : '0'); if (l <= pos - 1) addRun(l, pos - 1); if (pos + 1 <= r) addRun(pos + 1, r); int newL = pos, newR = pos; // merge left if there's a run ending at pos-1 auto itLeft = runs.upper_bound(pos); if (itLeft != runs.begin()) { --itLeft; if (itLeft->second == pos - 1 && s[itLeft->first] == s[pos]) { newL = itLeft->first; eraseRun(itLeft->first, itLeft->second); } } // merge right if there's a run starting at pos+1 auto itRight = runs.find(pos + 1); if (itRight != runs.end() && s[pos + 1] == s[pos]) { newR = itRight->second; eraseRun(itRight->first, itRight->second); } addRun(newL, newR); }
Drill Type:
MindsolveRefresh seg tree idea
Solutions:
D. Penchick and Desert Rabbit
Problem Summary:
We have N <= 5e5 pillars of height <= 5e5. We can jump from a pillar i to a pillar j>i if it is shorter. Or to a j<i if it is taller. Jump forward to shorter, backward to higher. What is the highest pillar we can reach for all starting points i?
Notes:
I processed pillars from highest to lowest. Obviously at the tallest pillar we have our answers. At the second tallest if there is a taller pillar before us we can take it, but maybe there is one on the right we need to reach: 10 15 _ 15 is highest 10 is where we are Maybe _ is shorter? From any position we can always reach the shortest position on the right < X. If there are no shorter positions to the right we cannot go right. If there is a shorter position, we can always reach it. So we know how far right we can go. Figure out the furthest right we can go from each position (furthest right number < X, used binary search + suffix min) and we could reach any tallest height left of that. Since we process pillars from high to low we know we can reach our pillar X or maybe one higher. It's like segment tree dp. Editorial idea is this: For a given index, we look at prefix max [...i] and suffix min [i+1...] If the pf max is > suffix min, we can always navigate to that max (either we are there, or we jump back) and then jump to the suffix min on the right. Now we can jump to i+1 always either by jumping back from the suffix min to i+1, or we directly jumped to i+1 from the pf max. So whatever i+1 could reach we could reach too. The prefix max at i+1 can only go up and the suffix min at i+1 can only go down so we could essentially reach i+2 and so on. Or something like this I'm not fully lucid rn. Anyway if pf max is <= suffix min we can never cross the boundary and so our best is the pf max. This idea is O(n) unlike my seg tree
Drill Type:
MindsolveRefresh the idea / look at code quickly, gloss over editorial idea just to stay aware of some ideas like this
Solutions:
C. Penchick and BBQ Buns
Problem Summary:
We want to serve N <= 2e5 buns. We have 1e6 types of buns. If we place a bun type we must place at least 2. Distances between 2 buns of the same type must always be a perfect square. Construct a sequence or determine impossible.
Notes:
Even n can always be done: 1 1 2 2 3 3 ... Odd n is tricky. We need to place an odd number of buns at some point. We need A<>B to be a perfect square, B<>C, and A<>C. Minimum this is true is 1 10 26 (0 9 25 basically, 1-indexed). As there is some integer X Y and Z for X^2 + Y^2 = Z^2. This is a 3 4 5 triangle. We show this construction: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 X X X But there are an odd number of gaps from 11 to 25 so it is not doable. As in total we have an odd number of buns left to be placed and cannot place any more odd amounts. Extend to 27: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 X X Y X Y Now the gaps are even and we can fill the rest.
Drill Type:
MindsolveRemember this extension idea, just refresh how you could not make that last logic leap
Solutions:
B. Penchick and Satay Sticks
Problem Summary:
We have a permutation of size N. We can switch two adjacent numbers if their difference is 1. Can we sort the array?
Notes:
1 can only ever be swapped with 2. So either 1 is in the right spot or it is in the 2nd spot and 2 is in the first spot. Basically scan left to right and if the number is in the right spot continue. If not, try to swap the 1 in. If it wasn't swappable or that isn't a 1 we fail. Otherwise we now have a new permutation essentially of size n-1.
Solutions:
A. Penchick and Modern Monument
Problem Summary:
We have a mono-decreasing array of size N <= 50 and A[i] <= 50, we need a mono increasing array. In one operation we can change the height of a building. Find the min # of operations to make it mono increasing.
Notes:
For a given height type, everything less than the height is on the right and everything more is on the left. All of those can be changed. We can at most leave all heights of a single type unchanged. Otherwise we violate the rule. So take n - max frequency.
Solutions:
B. Lady Bug
Problem Summary:
We have two binary strings of length N <= 2e5. We can swap A[i] and B[i-1] and B[i] and A[i-1]. Can we make A all 0s?
Notes:
Observe we basically have two separate chains that can swap, even A indices + odd B indices, and odd A indices + even B indices. Among those, we can form any sorting we like. Ensure we have enough 0s to go into A, in both portions.
Solutions:
A. Kamilka and the Sheep
Problem Summary:
We have n <= 100 sheep with all different beauties A[i] <= 1e9. We select two sheep and can both increment them by a non-negative integer d. What is the max gcd we can obtain of a pair after this one operation?
Notes:
Claim: If we have two sheep with A and B where A<B we can always achieve B-A. We set A to be some multiple of their difference, now B is A+that difference, so they share that factor. It is impossible to have A and B share a factor greater than their difference. Because A would be at some multiple of the difference and B is then bounded by at most the difference. So the answer is max - min.
Solutions:
C. Asuna and the Mosquitoes
Problem Summary:
We have an array of towers. N <= 2e5, A[i] <= 1e9. In an operation we can take two towers whose sum is odd and decrement one and increase one. Min tower height can be 0. What is the tallest tower we can form?
Notes:
If all towers are even or all odd we cannot do anything. Now there is at least one even and one odd. The odd can eat all the evens. We want to eat the odds too but we cannot. We could sacrifice 1 from an odd by putting that into a 0 tower, then consume the remainder. We definitely have at least one 0 because we ate a full even tower. Proof of correctness: Invariants: An operation doesn't change the # of odds and evens. So a max score is all evens are 0, all odds are 1, and everything else in the remainder.
Solutions:
3730. Maximum Calories Burnt from Jumps
Problem Summary:
Jumping from one height to another burns abs(height1 - height2)^2 calories. We have to jump on N <= 1e5 blocks, A[i] <= 1e5, what is the max number of calories we burn? We start at the ground (height 0).
Notes:
Jump to highest, then lowest, then 2nd highest, and so on
Solutions:
3631. Sort Threats by Severity and Exploitability
Problem Summary:
We have N <= 1e5 threads of [id, severity, exploitability]. Return them sorted by descending threat score and increasing id. Threat score = 2 * sev + exp
Notes:
Literally just pass a custom sorter lambda
Solutions:
3792. Sum of Increasing Product Blocks
Problem Summary:
We are given an n <= 1000, for each term we add these up (% some MOD) 1: 1 2: 2 * 3 3: 4 * 5 * 6 4: 7 * 8 * 9 * 10 What is the final sum?
Notes:
We can literally enumerate the n^2 options that is optimal. We could precompute these before to share across tests but it is the same complexity.
Solutions:
3793. Find Users with High Token Usage
Problem Summary:
Given a SQL table of user prompts we need to select all users who have submitted at least 3 prompts, where one prompt was above their average, and also get their average prompt token usage
Notes:
Remember that HAVING filters out if we keep a group or not
Solutions:
N-th Prime
Problem Summary:
Print the n-th prime, n <= 5e5
Notes:
We can just make a boolean isPrime array size 1e8 and know that exceeds n primes. There is some heuristic to estimate apparently. There are better ways since it is possible to print all primes up to 1e9 with some segmented sieve + wheel thing I haven't learned it though https://github.com/ShahjalalShohag/code-library/blob/main/Number%20Theory/Sieve%20upto%201e9.cpp
Drill Type:
MindsolveJust re-read notes
Solutions:
Stick Divisions
Problem Summary:
We have a stick of length x <= 1e9. We must divide it into N <= 2e5 sticks each of length <= 1e9 (they add to X) that are given. The cost to divide a stick of size Y is Y. What is the min cost to reach our desired set of sticks?
Notes:
We can take the split up sticks and repeatedly merge them based on the cheapest 2. To be honest I don't know a great proof of correctness here but I kind of get some MST union two cheap nodes vibe though GPT says that isn't airtight.
Drill Type:
MindsolveJust review this idea since I don't know proof of correctness
Solutions:
1421. NPV Queries
Problem Summary:
Given 2 SQL tables with shared composite keys we need to extract all of a column from one table or force it to 0
Notes:
We can LEFT JOIN the column to preserve all records, and if not present COALESCE to 0 Good practice for join on composite fields
Solutions:
F. Group Projects
Problem Summary:
We have N <= 200 coders each with skill <= 500. We must split them all into groups. The penalty of a group is maxSkill - minSkill in that group. We can allow at most X <= 2000 penalty across all groups. How many ways can we divide the groups?
Notes:
We sort the coders and track how many open intervals we have. dp[openIntervals][penaltySoFar] For each coder we could put it in its own group, add it to an existing group (remember to factor how many groups we could add it to), close an existing group, or open a new group. There is an element of combinatorics here. I used push DP. I also "paid the tax" for the groups up front. The penalty transition is a bit weird. The penalty represents the total penalty across all completed groups but also the ongoing penalty of open groups. As we increment, the penalty increases for each group based on the diff between A[i] and A[i + 1], or A[i] and A[i - 1] depending how you frame it. I had tried some other ideas like dp[openIntervals][penaltyFromClosedIntervals] but I couldn't get a right formulation. This is the same as CSES: Group Projects, that one is in the drill system this one is not
Solutions:
Coding Company
Problem Summary:
We have N <= 100 coders each with skill <= 100. We must split them all into groups. The penalty of a group is maxSkill - minSkill in that group. We can allow at most X <= 5000 penalty across all groups. How many ways can we divide the groups?
Notes:
We sort the coders and track how many open intervals we have. dp[openIntervals][penaltySoFar] For each coder we could put it in its own group, add it to an existing group (remember to factor how many groups we could add it to), close an existing group, or open a new group. There is an element of combinatorics here. I used push DP. I also "paid the tax" for the groups up front. The penalty transition is a bit weird. The penalty represents the total penalty across all completed groups but also the ongoing penalty of open groups. As we increment, the penalty increases for each group based on the diff between A[i] and A[i + 1], or A[i] and A[i - 1] depending how you frame it. I had tried some other ideas like dp[openIntervals][penaltyFromClosedIntervals] but I couldn't get a right formulation.
Drill Type:
ImplementGood practice to sharpen ndp push skills and remember this complex technique
Solutions:
Road Construction
Problem Summary:
We have N cities. Every day we connect two of them. Report the max size of a group of cities and the number of groups.
Notes:
Very standard union find
Solutions:
Common Divisors
Problem Summary:
Given N <= 2e5 numbers <= 1e6, find the max GCD of two numbers.
Notes:
We could enumerate all factors from 1 to 1e6 and use harmonic series to check how many numbers are divisible by that. What if A[i] <= 1e9? We could prime factorize every number then generate all factors using the primes. To prime factorize numbers up to 1e9 we could generate all primes up to root(1e9) which is around 3400. Then for a given number we could just loop over all of those primes which is 3400*n time and also get their complement factors and use DMA to check if those are prime but that might end up being too slow. There is also some trick like we take our number say 14 and we enumerate primes up to root(14) and divide each time we get there if it is a factor. So 14/2 = 7 now 7 is remaining. We keep going (no SPF is required for this, we literally are looping on the 3400 primes). Once we expend all the root(1e9) primes we have some remaining number. We can have at most one prime factor > root(1e9) otherwise the two would multiply together to be > 1e9. That last remainder must be prime. If it were composite it would have at least one prime factor < root(1e9). So it must be prime. So with this method we could essentially prime factorize a number <= 1e9 in 3400 time and from each numbers generated primes we can generate all factors. This takes O(divisors) time which is around 1000 max for numbers <= 1e9. Then we find the two highest common divisors. Also this might be too slow anyway since thats around 4.4e8 but in practice it may be fast enough There might be faster techniques like pollard rho I'm not yet familiar with them.
Drill Type:
MindsolveRe-read notes on different ideas
Solutions:
D. Power Products
Problem Summary:
Given N <= 1e5 numbers A[i] <= 1e5, and k <= 100, find the # of pairs of numbers whose product can be expressed as x^k for some integer x
Notes:
To write a number as x^k we need all its prime factor exponents to be divisible by k. So we prime factorize a number and look up the inverted remainders in a hashmap to update result.
Drill Type:
MindsolveJust a quick review on the technique moreso for the number theory
Solutions:
D2. Up the Strip
Problem Summary:
We are at cell X. In one move we can subtract some Y < X and move to X-Y. We can also floor divide X by some 2 <= Y <= X and move to X//Y. So 10 can be divided by 2...9 and move to 10//2...10//10. How many ways can we reach cell 1?
Notes:
Prereq: Read the part 1 version of this problem first to understand N rootN solution N root N is not sufficient for this unlike part 1. Refer to part 1 for the quotient bucket method. Even if we enumerated all quotient buckets (root(N)) for N numbers, that DOES not amortize to N log N. A number can take on root(N) unique quotients like 100//2 -> 50, 100//3 -> 33, etc, but that doesn't mean the same thing as the # of divisors. There are more quotients (like 100//3) than divisors. Recall the # of divisors for all numbers 1...n is up to n log n work. Proof: Iterate on all divisors 1...n and their multiples, harmonic series style, which is n log n. If somehow we can use this fact we can attain n log n time complexity. Take some number like 7 which has these floor divisions: 7 -> 3, 2, 1, 1, 1, 1 (2, 3, 4, 5, 6, 7) When we increment to 8: // 8 -> 4, 2, 2, 1, 1, 1, 1 (2, 3, 4, 5, 6, 7, 8) So we add a single dp[1] (for the number 8 itself), and any proper factors like 2 and 4 lose their old dp and gain an updated dp. So the 2 now fits into 8 4 times instead of 3, so we would minus dp[3] and add dp[4]. We can then transition in # of divisors time which amortizes to n log n. We need to maintain sumOverDivisors dp prefix and transition that. There is a more fucked method. Say we just solved dp[5]. This is going to contribute to future cells. For instance cells 10-11 can floor divide by 2 and gain a dp[5]. Cells 15-17 can floor divide by 3 and gain a dp[5]. So once we solve a dp[x] we enumerate up and I think use a sweepline esque thing to indicate contributions. Need to think about the proof of this more for time complexity and the general solution is just wack
Drill Type:
Implement-Implement the sumOverDivisors version -mentally refresh the bottom up harmonic series variant
Solutions:
D1. Up the Strip (simplified version)
Problem Summary:
We are at cell X. In one move we can subtract some Y < X and move to X-Y. We can also floor divide X by some 2 <= Y <= X and move to X//Y. So 10 can be divided by 2...9 and move to 10//2...10//10. How many ways can we reach cell 1?
Notes:
For the subtraction part that is a very simple prefix DP, just a single variable. For the divisors, we could enumerate all N options, so divide 10//1, 10//2, ... 10//10 but that is O(n^2) overall. Instead we observe we can only get root(X) unique quotients when doing floor division. Proof: Any factor < root(X) can produce a value. So for 100, all factors 1-10 we let count as a unique quotient. Any factor >= root(X) (so 10 to 100) our quotient is already root(X) when dividing by the first 1. Like 100//10 is already 10, so it can drop at most root(X) more times. So if we can quickly figure out these buckets we can have a rootN recurrence. Start enumerating divisors in order from 2 to X, but compute the highest divisor that would result in the same quotient. For instance 100//13 is 7. Then we do 100//7 and get 14. So the upper boundary is 14. So the width is 2. We add 2 * dp[7]
Drill Type:
ImplementImplement the quotient bucket trick
Solutions:
3817. Good Indices in a Digit String
Problem Summary:
A string of numbers is good if for some index i, s[i:...] equals that index
Notes:
We can just manually check each index, n log n time
Solutions:
3415. Find Products with Three Consecutive Digits
Problem Summary:
Given a SQL table return products with names containing 3 consecutive digits
Notes:
regex in sql
Solutions:
3740. Minimum Distance Between Three Equal Elements I
Problem Summary:
Find the minimum distance between 3 indices of different numbers, small N
Notes:
brute force, refer to the second version for a harder one
Solutions:
3741. Minimum Distance Between Three Equal Elements II
Problem Summary:
Find the minimum distance i+j + j+k + i+k between three difference indices i<j<k where nums[i] == nums[j] == nums[k]
Notes:
Store the last 2 indices for each number and scan and update the results
Solutions:
3750. Minimum Number of Flips to Reverse Binary String
Problem Summary:
Find the # of bit differences between X and the reverse of X
Notes:
Just flip X and count
Solutions:
3773. Maximum Number of Equal Length Runs
Problem Summary:
We have a string like "abbbccaa" find the max frequency of consecutive lengths, so a = length 1, cc and aa = length 2, bbb = length 3, max frequency is 2
Notes:
Just count the length as you go and update
Solutions:
3758. Convert Number Words to Digits
Problem Summary:
We have a string of letters containing some word substrings, like "onextwoabcthree", return a string of the extracted numbers "123"
Notes:
We can just check each window manually
Solutions:
3763. Maximum Total Sum with Threshold Constraints
Problem Summary:
We have thresholds[i] and nums[i]. Every second we unlock a new threshold + 1 and we can pick a number from nums <= that threshold. What is the maximum score we can get?
Notes:
Zip and sort and enumerate the thresholds and add to result, until the time is too great
Solutions:
2687. Bikes Last Time Used
Problem Summary:
Given a SQL table of bikes and their usage times, find the last time each bike was used
Notes:
GROUP BY the bike_id and MAX on the usage time
Solutions:
3672. Sum of Weighted Modes in Subarrays
Problem Summary:
For all windows of size K, sum the mode * the frequency of the mode. If there is a mode tie, pick the smallest number.
Notes:
We can have a MaxFrequencyTracker with some bookkeeping, number -> frequency and frequency -> SortedList (or heap) of numbers.
Solutions:
3682. Minimum Index Sum of Common Elements
Problem Summary:
Given 2 arrays of numbers, find the smallest i+j such that nums[i] == nums2[j]
Notes:
Record the earliest index for each number
Solutions:
3687. Library Late Fee Calculator
Problem Summary:
Calculate the late fee of many books following a certain set of rules
Notes:
Genuinely top 5 easiest questions in leetcode
Solutions:
3702. Longest Subsequence With Non-Zero Bitwise XOR
Problem Summary:
Find the length of the longest subsequence of nums with an XOR > 0
Notes:
Either the entire array has an XOR of non-0, or we can remove a single non-0 element, or everything is 0
Solutions:
3696. Maximum Distance Between Unequal Words in Array I
Problem Summary:
Find the maximum distance between 2 words that are different.
Notes:
Compare 0th index to all numbers and n-1th index to all numbers
Solutions:
3717. Minimum Operations to Make the Array Beautiful
Problem Summary:
We can increment a number in an array by 1. Find the minimum # of increments such that every number is divisible by the previous number. N <= 100 A[i] <= 50
Notes:
Dp(i, prev) is at most 100 * 50. No reason to have a number exceed 50 ever. We can loop through 50 options or just multiples of the previous number.
Solutions:
2356. Number of Unique Subjects Taught by Each Teacher
Problem Summary:
Given a SQL table count the # of distinct subject_id per teacher_id
Notes:
group by teacher and use COUNT distinct
Solutions:
Next Prime
Problem Summary:
Given t <= 20 numbers <= 1e12, compute the next prime.
Notes:
Prime gaps are small (~28) so we can iterate and do a fast prime check on each. For example deterministic miller rabin is logN and we do this for t=20 cases and expect 28 numbers to check is 20 * 28 * logN. We could also do a basic trial division up to rootN which would be t * 28 (really 14 since we only need to check odds) * rootN The average prime gap around M is ln(M)
Drill Type:
MindsolveRemember the ideas about checking primes quickly, trial division also probably works Implement the segmented sieve, probably a better version than your existing code which is quite messy
Solutions:
C. Reducing Fractions
Problem Summary:
We are given two arrays A and B of size <= 1e5 with numbers <= 1e7. The product of A represents a numerator and the product of B represents a denominator, and this is a fraction. We need to simplify it. We need to return a new numerator and denominator array of size <= 1e5 with numbers <= 1e7 which is maximally simplified, so there is no common factor between the top and bottom.
Notes:
Note that while any prime factors are shared between the 2 it can be reduced. I computed the # of prime factors for all primes in the top and bottom by creating an SPF array then quickly prime factorizing all numbers. Now we have aCnt and bCnt for primes. If aCnt has 8 powers of 3 and bCnt has 6, the numerator should end up with 2 and the denominator 0. Set up a mustRemove[prime] counter (in this case it would be 6 as we remove 6 from the top and bottom) to make the implementation easy. Now loop along each A[i] and then after B[i]. Fast prime factorize with spf again and any time we must remove prime factors, do so, and update the array. We work on A and B as our result because they already satisfy the constraints. If we tried to just output 1 occurrence of each prime (for instance the numerator [2, 2] if we had two extra 2s) we would overflow the 1e5 length requirement. If we tried to greedily compress the 2s together as long as the number is <= 1e7 we would still fail (I failed a test), hard to prove why but intuitively we won't know how to tightly pack them.
Drill Type:
MindsolveRe-read solution and remember this constructive concept of using the input array
Solutions:
D. Soldier and Number Game
Problem Summary:
We are given N <= 1e6 queries [a, b] where a,b <= 5e6. For each query, we need the maximum number of factors we can divide over and over in a!/b!. So like 100 could be 10 x 10 (score 2) or 2 x 2 x 5 x 5 (score 4, which is max).
Notes:
Alway take primes. We need to know the # of prime factors in a given number quickly for which we can use SPF and it should be log(log(M)) to compute as we divide, on average. For a!/b! we basically need a sum query from b+1:a for the # of prime factors of each.
Solutions:
B. T-primes
Problem Summary:
For N <= 1e5 numbers A[i] <= 1e12 check if they have 3 factors.
Notes:
A number with three factors is a perfect square of a prime. Precompute primes and check if the square root of each number is prime.
Solutions:
C. Kanade's Perfect Multiples
Problem Summary:
We have N <= 2e5 numbers A[i] <= 1e9. And a k <= 1e9. We need to create a set of numbers B such that all multiples of each B[j] that are <= k are in A. And all numbers in A contain a divisor in B.
Notes:
The smallest in A that has no divisors in B, must be chosen separately. We choose that to put in B and loop over all multiples marking them as accounted for in A. Also if one of those multiples doesn't exist in A we have an impossible situation. We repeat this process for all smallest numbers over and over. WRONG: Remember we mark multiples until we fail to have that multiple in A, so at most we can mark up to |A| times. Because we might be marking multiples that were already marked. A loose bound looks like we would try all numbers 1, 2, 3, ... N and their multiples up to 1e9 but somehow the complexity amortizes I don't have an airtight argument for this Some other ideas that failed: All primes must be chosen (unless 1 can be chosen). Then go small numbers to large. If the first number had no prime factors picked then this number must be picked. But future numbers could have no primes picked but still a normal factor picked. Like [4, 8] we pick 4 but at 8 it's not enough to just check primes we must check factors so this does not work.
Drill Type:
MindsolveRefresh on the amortized idea of harmonic series here and think about failed ideas
Solutions:
F. We Were Both Children
Problem Summary:
We have N<=2e5 frogs with hopping distances up to 1e9. Each frog will go to spots hop, 2 * hop, 3 * hop, etc. Find a spot from 1 to N where we can see the most frogs.
Notes:
Get the frequency of every hop type and use harmonic series.
Solutions:
B. Sherlock and his girlfriend
Problem Summary:
We have N <= 1e5 pieces of jewelry. Color all of them such that no pair (i, j) is the same if i is a prime divisor of j.
Notes:
Any non prime can be one color and any prime can be the other.
Solutions:
204. Count Primes
Problem Summary:
Count the # of primes < N <= 5e6
Notes:
Refer to CSES: Counting Divisors for full notes
Solutions:
Counting Divisors
Problem Summary:
Given a number N <= 1e5 we will get N queries of numbers <= 1e6, report how many factors those numbers have.
Notes:
Naive solution, for a given factor we add contributions, so 1 contributes to 1, 2, 3, ... X. 2 contributes to 2, 4, 6, .... Then to answer queries we output in O(1). It takes X log X time to build the counts and N time to answer queries, N + X log X. Another solution is if we know the smallest prime factor "spf" for all numbers, we can divide a number by its spf repeatedly and use that info to compute # of divisors. If a number has 2^3 * 3^1 * 5^4 it has 4 * 2 * 5 options of factors. So we divide by the SPF and track the exponent, when the spf changes we multiply these together. On average a number M has log log M prime factors (ramanujan) so each query would take log log X time. To build the spf array we can use a prime sieve but mark which number is the spf. This can be done by iterating on a number and then its multiples and marking composites. We only need to mark composites when the number itself was prime. For instance 4 is not prime so we don't iterate on 8 12 16 etc since we know those will be marked. Naively this is N log N with harmonic series but in practice it is N log log N not sure how. We can mark the spf of a number every time we mark it. We do: for divisor in range(1, MAX_X +1) ... check if this divisor is prime (never had an spf set) for mult = 2 * divisor; multi <= MAX_X; mult += divisor mark spf here However we can make some optimizations, see the "sieves.py" guide for notes but a few callouts: -mult can start at divisor**2 not divisor*2, because any number < divisor would have marked any multiples. But this requires some long long casting like for long long mult = 1LL * divisor * divisor. Doesn't change complexity or I think runtime very much. -We can loop divisor up to root(MAX_X) not MAX_X. Remember the goal of the outer loop is to mark larger composite numbers as not prime. But if our factor is > root(MAX_X) then any multiple of it would have a factor less than root(MAX_X) which would already be marked. The only downside is the outer loop won't mark spf[somePrime] = somePrime, for instance MAX_X = 100 we don't ever mark spf[13] = 13, it stays 0. But implicitly anything with an spf=0 is prime. Also if we are just checking a bool array isPrime = [True] * n we aren't worried at all because those isPrimes are already true so stopping the loop on root(MAX_X) is totally fine.
Drill Type:
ImplementImplement different versions of this: -Harmonic series -SPF and repeatedly factorize numbers + use combinatorics -DP on divCount and spfPower -Re-read notes and understand different sieves and complexities
Solutions:
666. Path Sum IV
Problem Summary:
Given a tree with a weird structure / format, return the sum of all root<>leaf paths.
Notes:
Use the root=1, left child = 2*i and right child = 2*i + 1 system to handle the weird format. I did dfs(node, prefixSum) as we descend and I used a global result to update the answer when I hit a leaf. We can avoid the global by making the DFS return a value, GPT: "Yep. You can make DFS return “sum of all root→leaf path sums in this subtree, given that we start at this node”." Like this: def dfs(i, prefixSum): if i not in idxToNode: return 0 val = idxToNode[i] % 10 prefixSum += val left, right = 2*i, 2*i+1 if left not in idxToNode and right not in idxToNode: return prefixSum return dfs(left, prefixSum) + dfs(right, prefixSum) return dfs(1, 0) So I guess the DFS returns the "this node to leave path sums" We can do it without the prefixSum parameter too: GPT: If you really want DFS to not carry a prefix, you can return two things from each node: leafCount: how many leaves are in this subtree sumFromHere: sum of path-sums from this node down to leaves including this node’s value Then parent can combine without needing a prefix: def dfs(i): val = idxToNode[i] % 10 left, right = 2*i, 2*i+1 hasLeft = left in idxToNode hasRight = right in idxToNode if not hasLeft and not hasRight: return (1, val) # 1 leaf, sum of paths (just val) leafCnt = 0 childSum = 0 if hasLeft: c, s = dfs(left) leafCnt += c childSum += s if hasRight: c, s = dfs(right) leafCnt += c childSum += s # every path below gets +val once return (leafCnt, childSum + val * leafCnt) leafCnt, total = dfs(1) return total
Drill Type:
MindsolveRe-read the concept for DFS returning a value instead of using a global and understand the implementation Re-read the second solution without the prefix sum parameter too
Solutions:
1303. Find the Team Size
Problem Summary:
Given a SQL table of employee_id and their team_id, output employee_id and the size of the team they are on
Notes:
Good practice with JOIN
Solutions:
1173. Immediate Food Delivery I
Problem Summary:
Given a SQL table of food orders find the % of orders where the order date is the same as the delivery date
Notes:
Good practice all around using CASE, ROUND, understanding COUNT(*)
Solutions:
1082. Sales Analysis I
Problem Summary:
We have a SQL table of sales, select every seller_id that had a max total price of sales.
Notes:
I tried this at first: -- Write your PostgreSQL query statement below SELECT seller_id, SUM(price) AS price_sum FROM Sales GROUP BY seller_id; The issue is this will show every seller<>total sales but I only want to show the top amount(s). GPT showed this: SELECT seller_id FROM Sales GROUP BY seller_id HAVING SUM(price) >= ALL ( SELECT SUM(price) FROM Sales GROUP BY seller_id ); "ALL lets you compare a value against every value returned by a subquery." I asked this: "how can we do having SUM price when we didnt select price in that select though, you only selected the seller id" GPT said this: Because HAVING is allowed to use aggregate expressions that are computed from the rows in each group, even if you don’t output them. In a grouped query, Postgres conceptually does: FROM → get rows GROUP BY seller_id → make buckets compute aggregates per bucket (SUM(price), COUNT(*), etc.) HAVING ... → keep/discard buckets using those aggregates SELECT ... → choose what columns to output for each remaining bucket So this is totally valid: SELECT seller_id FROM Sales GROUP BY seller_id HAVING SUM(price) >= 1000; You’re filtering groups by their sum, but you’re only displaying the seller_id. Also GPT gave another solution here: WITH s AS ( SELECT seller_id, SUM(price) AS total FROM Sales GROUP BY seller_id ) SELECT seller_id FROM s WHERE total = (SELECT MAX(total) FROM s);
Drill Type:
ImplementRead through notes and resolve
Solutions:
1050. Actors and Directors Who Cooperated At Least Three Times
Problem Summary:
We have a SQL database ActorDirector and need to find all actor_id director_id pairs that have occurred >= 3 times
Notes:
We could use a subquery to first get the counts and an outer query to get the rows with count >= 3 (commented out code in github) or we can use HAVING. Remember WHERE filters before the group by and HAVING filters after.
Solutions:
1069. Product Sales Analysis II
Problem Summary:
Given a SQL sales table with product_id, quantity sold, return a table of each product id with how much it sold
Notes:
Standard SELECT + sum aggregator on a group by product
Solutions:
3816. Lexicographically Smallest String After Deleting Duplicate Characters
Problem Summary:
We have a string of letters. We can keep picking 2 of the same letter and delete one. Find the lexicographical minimum string.
Notes:
Hard hard hard. I am stronger tomorrow.
Drill Type:
ImplementSolve it yourself
Solutions:
3815. Design Auction System
Problem Summary:
Design an auction system, support users bidding on items for different amounts, updating bids, getting the highest bid and bidder for an item, and removing bids.
Notes:
Can manage this with sorted containers or a lazy heap
Solutions:
3814. Maximum Capacity Within Budget
Problem Summary:
We have machines with costs and capacities. We have a budget. What is the maximum capacity we can get stay under the budget, with up to 2 machines?
Notes:
Many ways to solve: -Prefix maximum + binary search, pick one item and binary search for the most expensive second item in the prefix and take a prefix max -I think we can adapt the above to use two pointers, starting at cheapest and most expensive items and tracking prefixes -Segment tree abuse to find the most in a range, like the binary search solution -Some mono-stack solution I did not read: https://leetcode.com/problems/maximum-capacity-within-budget/solutions/7503763/simple-python-monotonic-stack-by-townizm-38ve/ didn't list seg tree Apparently there is some 2 heaps idea I don't know didn't list it
Solutions:
3813. Vowel-Consonant Score
Problem Summary:
Just a basic string counting question
Solutions:
C. Serval and The Formula
Problem Summary:
We are given X, Y <= 1e9. We need to find a K <= 1e18 where (x + k) + (y + k) = (x + k) ^ (y + k) or show it is impossible.
Notes:
This is saying A + B = A ^ B. This only happens when A & B = 0, no bits can be shared. If A=B we cannot do anything as they will always be the exact same. Otherwise, set the bigger one to some higher power of 2 which will share no bits with numbers below it.
Drill Type:
MindsolveRemember the clean solution and your struggle with trying to greedily iterate from msb or lsb. Remember the simple A + B = A ^ B when no two set bits are shared.
Solutions:
B. Serval and Final MEX
Problem Summary:
We have an array of non-negative numbers of length >= 4. We can select a subarray and replace it with its MEX. Construct a sequence of operations where we get down to an array [0].
Notes:
To get [0] we must have an array with no 0s. I think the easiest way is if the left half of the array has 0s then operate on that to get a non-zero. Repeat on the right half. Now mex the whole thing. We could also arbitrarily mex the array down to n=4 and brute force from there. My solution was a bit more complex, if a boundary was 0 I mex'd it with its neighbor to get a non-zero boundary, for both boundaries. Then if 0 was in the middle I mex'd that. Then mex'd the whole thing.
Solutions:
A. Serval and String Theory
Problem Summary:
We have a string s. We need it to be lexicographically smaller than the reverse of s. In an operation we can swap two letters. Can we achieve this in <= k operations?
Notes:
If s < s' we win immediately. Then if k=0 we lose. If unique letters is 1 we lose immediately. Now we have an operation and two differing letters. If the two differing letters are start and end we can swap them. Otherwise we can swap the differing letter with one of the ends.
Solutions:
Digit Queries
Problem Summary:
Consider the infinite string of numbers 123456789101112... Answer q <= 1000 queries, what is the k <= 1e18 digit?
Notes:
Find how many full numbers of each width we pass, basically implementation practice
Drill Type:
ImplementPractice implementation, just free-style solve it
Solutions:
1890. The Latest Login in 2020
Problem Summary:
We have a SQL table with user_id and time_stamp Login times. Return a table for the last login in 2020 for each user.
Notes:
-First we need to select user_id from the table but also the MAX(time_stamp). -We will GROUP BY user_id -We will WHERE the time_stamp is in that date range
Solutions:
586. Customer Placing the Largest Number of Orders
Problem Summary:
We have a SQL table with columns order_number and customer_number. Find the customer_number who placed the most orders.
Notes:
-We can do a query where we GROUP BY customer_number but through in COUNT(*) AS Cnt to get a column with the count of those rows in the group. -Then do another outer query to grab the highest count, sorted by descending with limit 1.
Solutions:
610. Triangle Judgement
Problem Summary:
We have a SQL table Triangle with columns x, y, z that are numbers. Report all rows that can form valid triangles + an extra column Triangle with "Yes" or "No"
Notes:
-Triangle inequality: (x + y > z) and (x + z > y) and (y + z > x) -To add a column we use CASE / WHEN / THEN / ELSE / END AS
Drill Type:
Mindsolveremember triangle inequality
Solutions:
3811. Number of Alternating XOR Partitions
Problem Summary:
Given an array of numbers N <= 1e5 A[i] <= 1e9, and target1 and target2, find how many partitions of the array exist where each block XOR is target1, then target2, then target1, repeating.
Notes:
This is so hard. We will track endA and endB default dicts. endA[x] tells us the # of ways where our last block was target1, and the XOR of the entire prefix is x, as we enumerate on the array. Initially endB[0] = 1. As we add a new element we have some new prefix XOR. We wish a suffix partition to be equal to target1 or target2, meaning we need to look at some prior prefix. If we want a suffix block to be target2 we need to look at the number of ways we previously had an ending block of target1. But not just any previous ending, we use the prefix XOR to establish which ones we can look at. The ending of the solution is tricky too because we return addOne and addTwo specifically for only partitions that ended at n-1.
Drill Type:
Implementresolve this hard problem
Solutions:
3812. Minimum Edge Toggles on a Tree
Problem Summary:
We have an undirected tree where every node is 0 or 1, and a desired target list of 0s and 1s for each node. In an operation we can toggle both ends of an edge. Return a minimum # of edge flips or show it is impossible.
Notes:
I thought of a toposort, basically a leaf node must toggle if it needs to be switched. We could do a postorder DFS but toposort made sense to me in the moment (basically the same thing). This was a unique application of a topo sort because it was on an undirected tree so the implementation was a bit different. And a good lesson was to get the topo order first then process it after.
Drill Type:
ImplementRead my notes and also re-implement my weird topo sort
Solutions:
3810. Minimum Operations to Reach Target Array
Problem Summary:
We have two arrays of numbers, nums and target (same length). In one operation we can pick all maximal contiguous subsegments of the same type from nums (so if we pick number 5, pick all largest subarrays of only 5s) and make them match with the correct target numbers. Minimum # of operations needed to make nums equal to target?
Notes:
Every number type can be solved independently in one operation. So add all number types that mismatch to a set and return the length of that set.
Solutions:
3809. Best Reachable Tower
Problem Summary:
Towers exist on a 2d grid with [x, y] coordinates and a quality of q. Find the highest quality tower within a radius from our starting position, and in ties take the lexicographical smaller pair.
Notes:
Just linearly enumerate the towers and check
Solutions:
D. Reachability and Tree
Problem Summary:
We have a tree of <= 2e5 nodes. We need to make all edges directed. An ordered pair of nodes (u, v) is good if we can reach v from u. Is it possible to make the edges directed and have exactly N good pairs? Construct a solution if so.
Notes:
Note that by default all N-1 edges add 1 reachable section, so we just need one more. Structures like A>B>C>D add a lot of good pairs (too many) since we can reach things. Our tree must alternate directions, like: A v. v B. C ^^. ^ DE. F To prevent ever having too many good pairs. However we need one more good node than normal, so a single connected chain like A-B-C would become A>B>C, provided B cannot reach any other nodes. It is okay if C has other children and A connects to other things too. D < A > B > C < F v E So we just need to identify a node C by checking if any node has 2 edges. Then make another node next to it like A, the root, and construct the solution.
Drill Type:
MindsolveRemember the idea
Solutions:
C. Coloring Game
Problem Summary:
We have N <= 5000 balls with values <= 1e5. We will pick 3 and color them red. Opponent then picks one (can be a red ball) and repaints it blue. How many triplets can we have a strictly higher score?
Notes:
Try picking 2 balls A and B. Now the third ball C cannot exceed A+B or Bob could recolor C and win. So we have an upper bound. But it must be high enough such that A + B + C > max. So binary search for a range. I had to handle duplicates a bit separately, so I binary searched for a range that would make the C ball always bigger than B (so A B are distinct from C). Then I handled A=B=C separately and A, B=C separately. Two pointers could improve it from n^2 log n to n^2.
Solutions:
B. Shrinking Array
Problem Summary:
We have an array of numbers and in an operation we can replace two adjacent elements with some number between them, inclusive. What is the minimum # of operations to have an adjacent pair with a diff <= 1?
Notes:
If we already have it, return 0. If we are strictly ascending 1 3 5 9 we cannot form it. Otherwise there must be a peak like 152 or a valley 936 and we can take 1 operation.
Solutions:
A. Race
Problem Summary:
We have bob at some point on a number line and two prizes. We can choose where to start at. Can we guaranteed get either prize before bob?
Notes:
Just check if bob is on one side of both points
Solutions:
E. Unpleasant Strings
Problem Summary:
We have a string S of size <= 1e6 and up to Q <= 2e5 other strings (with total length at most 1e6). For each string answer how many more letters we need to append so that it is not a subsequence of S.
Notes:
To quickly check if a string t is a subsequence of s we use nxt[i][char] to only spend O(t) time. Now if we are a subsequence we know where we ended and then we use worst[i][c] to find the furthest right character to jump to. My implementation for worst[i][char] was easier if it corresponds to a suffix, not including `i`. Same with nxt[i][char]. Then I compute an O(26) size first[char] array to figure out where to start. But we also need a dp[i] to stack on top of the worst chains so that a query is O(1) after the O(t) portion.
Drill Type:
MindsolveRefresh mindsolve on this
Solutions:
1037. Valid Boomerang
Problem Summary:
Check if 3 points are distinct and not on the same line
Notes:
We can compare slopes and to avoid fractions, we want to simplify X/Y. This can be simplified while they share a factor, so divide both by their GCD.
Drill Type:
ImplementImplement slope hashing: def normSlope(p1, p2): rise = p2[1] - p1[1] run = p2[0] - p1[0] if run == 0: return (1, 0) # sentinel g = gcd(abs(rise), abs(run)) rise //= g run //= g if rise < 0: rise = -rise run = -run return (rise, run) EDIT drill 1: Got it working except I fell for the trap where I have (-1, -1) as a slope, forgot to normalize numerator to always be positive
Solutions:
1041. Robot Bounded In Circle
Problem Summary:
We have a robot at 0,0 and it has instructions to go up, right, down, and left of various lengths, it loops this forever. Is the robot in a bounded range?
Notes:
Check if the ending position is 0,0 as well, otherwise we drift
Solutions:
64. Minimum Path Sum
Problem Summary:
We are in a grid from the top left and going to the bottom right, down or right only. Minimize path sum.
Notes:
Standard DP
Solutions:
228. Summary Ranges
Problem Summary:
Summarize ranges Input: nums = [0,2,3,4,6,8,9] Output: ["0","2->4","6","8->9"]
Notes:
Just iterate and solve
Solutions:
20. Valid Parentheses
Problem Summary:
See if a bracket sequence with {} [] {} is valid
Notes:
Just use a stack
Solutions:
3653. XOR After Range Multiplication Queries I
Problem Summary:
Support L...R queries where we multiply elements by V, spaced out by K. But small constraint.
Notes:
Just brute force it due to small constraint
Solutions:
793. Preimage Size of Factorial Zeroes Function
Problem Summary:
Call f(num) the number of trailing zeroes on num!. How many numbers X, have f(X) = a given K? K <= 1e9.
Notes:
Binary search on answer, use legendre's
Drill Type:
MindsolveJust remember how to solve this
Solutions:
197. Rising Temperature
Problem Summary:
We have a database with columns ID, date, temperature. Find all rows with a temperature bigger than the previous day.
Notes:
Join the table with itself shifted by 1, select when the temperature is bigger.
Drill Type:
ImplementPractice a basic join
Solutions:
196. Delete Duplicate Emails
Problem Summary:
We have a table with column id, and email address. Keep only the smallest id per email address (use a DELETE).
Notes:
Mental model for deletes: MENTAL MODEL: DELETE + USING (PostgreSQL) DELETE removes rows from ONE target table DELETE FROM Person; Meaning: Person is the only table rows can be deleted from SQL scans Person and deletes rows (all rows, since no condition) DELETE ... WHERE ... = delete rows that match a condition DELETE FROM Person WHERE email = 'john@example.com '; Meaning: Iterate over each row in Person If the WHERE condition is true for that row, delete it Only Person rows are deleted DELETE ... USING ... = delete from target table, but allow references to other tables General form: DELETE FROM target_table USING other_tables WHERE condition involving target_table and other_tables; Key idea: Rows are deleted ONLY from target_table USING tables are READ-ONLY helpers USING allows join-like comparisons while deciding which target rows to delete Think: "For each row in target_table, check if there exists a matching row in USING tables that satisfies the WHERE condition"
Drill Type:
ImplementPractice delete and review mental model
Solutions:
619. Biggest Single Number
Problem Summary:
We have a table MyNumbers with a column nums. Find the largest number appearing once or return null.
Notes:
First we can select on MyNumbers to remove duplicate numbers with GROUP BY. Then filter with HAVING COUNT(num) = 1; This returns a table of all numbers with frequency 1, we subquery to get the max
Drill Type:
ImplementReview notes for how group by relates to select and count from rows → groups, and then aggregates like MIN are defined on groups. Think of it as two phases Phase A: form groups (buckets) GROUP BY email partitions the table into buckets: bucket “john@…” contains rows with ids {1,3} bucket “bob@…” contains rows with ids {2} … At this point you do not yet have output rows. Phase B: produce one output row per bucket Now SQL evaluates the SELECT list once per bucket: email = the bucket label (same for the whole bucket) MIN(id) = take all id values in the bucket and compute the minimum So for john’s bucket: MIN({1,3}) = 1. That’s why it’s “safe”: you’ve told SQL how to collapse many ids into one value per group. Why “conflict” isn’t quite right It’s not that SQL “tries and then conflicts and then fixes it.” It’s that after grouping, you’re no longer allowed to ask for raw row columns (id) unless they’re: part of the group key, or computed from the group via an aggregate (MIN, MAX, COUNT, …)
Solutions:
1228. Missing Number In Arithmetic Progression
Problem Summary:
We have an arithmetic sequence [A, A + x, A + 2x, ...]. A number (not first or last) was removed, find it
Notes:
I kind of misread I didn't know the array was sorted so I did a counting sort solution Otherwise we can linearly iterate or even binary search on an index and guess what number it should be
Solutions:
Trailing Zeros
Problem Summary:
Find the # of trailing zeroes in N!. N <= 1e9.
Notes:
A trailing 0 is formed by a 2*5. There will be fewer 5! than 2! so how many factors of 5 are there. Amount of #s divisible by 5 we add 1 to result for each. Repeat for 25s, 125s, and so on. log(n) time
Drill Type:
MindsolveRemember legendre's formula
Solutions:
Two Knights
Problem Summary:
Find the # of ways to put 2 knights on an NxN chessboard for all N up to 10,000.
Notes:
# of total ways to place 2 knights is n^2 choose 2. For rectangles: X X X X X X X X X X X X We lose 2 copies for each, which we can calculate in O(1).
Solutions:
3701. Compute Alternating Sum
Problem Summary:
Sum even indices minus odd indices
Notes:
1 liner
Solutions:
3336. Find the Number of Subsequences With Equal GCD
Problem Summary:
We have N <= 200 A[i] <= 200, find the # of ways to select two subsequences (don't have to take all numbers) with equal GCDs
Notes:
dp(i, gcd1, gcd2) and we pick or not pick. Can precompute all GCDs.
Solutions:
3247. Number of Subsequences with Odd Sum
Problem Summary:
Find the # of subsequences with an odd sum
Notes:
Basic dp(i, parity) or bottom up can probably do with combinatorics too
Solutions:
C. Divine Tree
Problem Summary:
We have N <= 1e5 nodes from 1...N. We are given M <= 1e12. The divine-ness of a node is the minimum value from that node to the root of a tree. Can we form a tree with divine-ness M? If so return the edges.
Notes:
First note a tree with root 1 has the minimum divine-ness which is N, so below that is impossible. A max divine tree would be like 7->6->5->4... which is n * (n + 1) / 2, so we cannot make more than that. Start with a min organization: 1>2>3>4>5 To increase by 1 we can rotate: 2>1>3>4>5 Again: 2>3>1>4>5 Eventually 1 gets put on the back: 2>3>4>5>1 We can do it again with 2, eventually reaching: 3>4>5>2>1 I simulated with a deque. We can also think about a baseline we score 1 per node, so we have P = m - n remaining to score. Any time we put a number X before 1, we gain X-1 extra (if we put them in descending order, like 6 5 4 1 we gain 5 + 4 + 3). So we can take the biggest numbers that sum to our remaining target and put everything else after the 1.
Drill Type:
ImplementImplement wice's solution
Solutions:
B. Square Pool
Problem Summary:
We have a huge S x S coordinate pool table and balls at integer positions that are hit at 45 degree angles. They bounce. How many balls eventually go into a hole?
Notes:
It is the reflection vs. bouncing trick, count how many are on each diagonal those will go in
Solutions:
A. Square of Rectangles
Problem Summary:
We get 3 rectangles where the sides of r1 are >= sides of r2 are >= sides of r3, can we place them adjacent to form a square?
Notes:
I did a ton of if/else branching, and a small rotation trick at the end
Solutions:
D. Missing Subsequence Sum
Problem Summary:
We are given K <= N <= 1e6. Construct a sequence of at most length 25, where no subsequence adds to K, but we can create subsequence sums for all other 1...N.
Notes:
A standard summing problem would give 1 2 4 8 ... until our total sum is >= N. First construct up to K-1: 1 2 4 8 16 ... then some number that puts us at K-1. Now we can make 1 to K-1. We need K+1, the only number that can be placed is K+1. Now we can make 1 to K-1 and K+1 to 2K. We need 2K+1 so we place that. We might think we can place all numbers up to 4K+1 now, but we cannot make 3K+1 as it is a hole. We place 3K+1 and we might think we can make up to 7K + 2 but we cannot make 6K + 2. I kept doubling the hole and placing that and it worked but also needed some edge case handling. Wasn't the cleanest solution.
Drill Type:
MindsolveStay vaguely aware of how I solved this
Solutions:
C. Everything Nim
Problem Summary:
We have N piles of stones, A[i] <= 1e9, N <= 2e5. We can remove a number of stones from every pile at once, as long as all piles have that many stones. Last to remove wins. Who wins?
Notes:
Observe repeated piles do nothing: [1, 3, 3, 5] is equivalent to [1, 3, 5]. If we have 2 stones in our pile we can both deplete it fully, or force our opponent to deplete it, so we would be able to win no matter what. If we don't, we see what the opponents situation is. So iterate until we get a pile where we have at least 2, counting for previous subtractions.
Drill Type:
MindsolveRefresh the idea
Solutions:
B. Rectangle Filling
Problem Summary:
We have a 500x500 grid of black and white tiles. We can select two diagonal corners if they are the same color and flip the entire region to that color. Can we white or blackout the grid?
Notes:
If two diagonal corners are same color, we can do it immediately. Otherwise we have something like: W W B B (Or rotated 90 degrees) To white out those bottom black corners we would need a white in between them. So just check in between the edges on each side.
Solutions:
A. Card Exchange
Problem Summary:
We have N cards with numbers on them. We can exchange K of the same type for K-1 of any number. Min # of cards we can form?
Notes:
If we have K of a card, we can group it with any other number forming a cascade effect. Otherwise we can do nothing.
Solutions:
E2. Erase and Extend (Hard Version)
Problem Summary:
We have a string s of size <= 5e5. We need to form a string of size k <= 5e5. We can delete the last letter of s, or do s = s + s. After infinite operations, find the smallest lexicographical string we can form.
Notes:
First read the E1 solution. Then here is the greedy idea. There may also be other solutions like z-function that can be used but I'm just listing this greedy one / putting it in string algorithms. Don't really consider this constructive. We will enumerate prefixes greedily Say we have some prefix "db" and are considering if "dbc" repeated is better That c will compare to the start of our prefix, d, so it is better If we were at "db" and considering "f", clearly "db" + "d" is better than "dbf" and we fail if the letter is equal, like "dbca" considering "d" (in the test "dbcadabc") we don't know which sequence is better yet We store "dbca" as the best still but accept the new "d" as an option and keep going If we keep going a lot, say our initial prefix |AB| CDEFGHHIJK like everything after C is being marked as equal We don't need to mod our "indexToConsider" back to the beginning, I think because it is guaranteed the CDEFGH... portion is just ABABAB repeated
Drill Type:
ImplementSolve this
Solutions:
D. Deleting Divisors
Problem Summary:
We have a number N <= 1e9. On our turn we can subtract a divisor not 1 or N. If we cannot, we lose. If two players are playing optimally who wins?
Notes:
Some observations: If we are prime, we lose. If we can force the opponent into a prime, we win. If we subtract a number X, then new remainder is also divisible by X. Then the only way to get someone into a prime is to halve our number into a prime. If we subtracted some prime number divisor we can only get new numbers that are multiples of that prime, and to get a new number that is exactly that prime we halved it. We cannot get some other prime number (like 25 - some prime 5 lets say, could never produce a prime that isn't 5 (in this case it doesn't even make 5, it makes 20)), because that new number would have to have the factor we just subtracted. I made some of these observations but could not close the logic loop so I printed answers up to 1000 and noticed a pattern. Proper solution of casework: If we are odd, all divisors are odd, so we must subtract an odd. This means we will obtain a new even number, but it cannot be an even power of 2, since a power of 2 cannot have an odd factor. If we are even and not a power of 2, we must have an odd factor. If we subtract the odd divisor we will win. If we subtract an odd we give our opponent an odd which could be a prime (they lose) or an odd number where they must give us an even number that is not a power of 2. If n is even and a power of 2 we can halve it or make it an even number that is not a power of 2 but we proved that wins for the other player. So we have it. So we win on all evens except 2, 8, 32, etc
Solutions:
E1. Erase and Extend (Easy Version)
Problem Summary:
We have a string s of size <= 5000. We need to form a string of size k <= 5000. We can delete the last letter of s, or do s = s + s. After infinite operations, find the smallest lexicographical string we can form.
Notes:
My claim is that we should delete some amount of letters, duplicate until we exceed size K, then trim the remaining edges. If we were to remove some letters, duplicate, and remove more, then duplicate again I think it would be provably worse, need to think about it more requires some focus. But Jiangly pointed out a good equivalence, s1^infinity < s2^infinity means s1 + s2 < s2 + s1: https://codeforces.com/blog/entry/91381?#comment-805703 Consider ABCD (don't worry about the actual letters for now), if we cut off D then duplicated: ABCABC And if we claimed we wanted to cut off more and duplicate again: ABCAB ABCAB It's sort of like claiming AB is better than ABC we should have just cut off more to begin with. So our string s with some ends chopped off, plus more of the start of s, is better as an infinite sequence if that is less than s itself. With jiangly's observation we can just test all prefix lengths duplicated and see which is the smallest. Since constraints are small we can do n*k.
Drill Type:
MindsolveRemember the string equivalence
Solutions:
C. Challenging Cliffs
Problem Summary:
We have an array A[i] <= 1e9, N <= 2e5 and adjacent numbers that are monotonically increasing add 1 difficulty. So [1, 1] or [2, 5]. We need to arrange the array such that abs(A[0] - A[-1]) is minimized, what is the max difficulty we can make?
Notes:
Great question, visualize the array as a monotonically increasing line chart. We find two heights that have a minimum differences like 3->4 and make the right portion the start, so 4..., and the left portion the end, so ...3. This makes only one point in the chart drop and we only lose 1 difficulty. If the length of the array is 2 though, we just return the sorted pair.
Solutions:
B. Bad Boy
Problem Summary:
We are in a 1e9 x 1e9 grid. We can pick two cells to move to orthogonally and then back to our start. Which two to maximize distance?
Notes:
I enumerated all pairs of corners to visit but I think we can make an observation that any opposite pair of corners is optimal.
Solutions:
A. Arithmetic Array
Problem Summary:
Given an array of integers (can be negative), find the minimum # of non-negative numbers to add to make the mean 1.
Notes:
Casework: If 1 already we are done If less than 1 we can always add a single number Otherwise add 0 sum-length times.
Solutions:
36. Valid Sudoku
Problem Summary:
Check if a 9x9 partial filled sudoku board is valid (not necessarily solveable),
Notes:
Scan over rows, columns, and boxes. Use box hashing const rowGrouping = Math.floor(rowNumber / 3); // rows 0-3 -> 0, 4-6 -> 1, 7-9 -> 2 const colGrouping = Math.floor(colNumber / 3); // cols 0-3 -> 0, 4-6 -> 1, 7-9 -> 2 // if we are in rowGrouping 0, we know we are in boxes 0, 1 or 2 // if we are in rowGrouping 1, we know we are in boxes 3, 4, or 5, etc // our first possible box we could be in, based off of the rowGrouping, is (rowGrouping * 3) // the colGrouping then provides an offset to increment by const boxNumber = rowGrouping * 3 + colGrouping;
Drill Type:
Mindsolverefresh box hashing (for interviews)
Solutions:
14. Longest Common Prefix
Problem Summary:
Find the longest common prefix among N strings (sum of lengths is small)
Notes:
It's just brute force check one letter of each string at a time, optimal complexity
Solutions:
9. Palindrome Number
Problem Summary:
Return true if the number X is a palindrome
Notes:
To do with just math we can "pop" the last digit by mod 10 and build out a reversed number, then compare those 2
Drill Type:
MindsolveMindsolve the math reversal technique
Solutions:
1. Two Sum
Problem Summary:
Find the indices of two numbers that add to X
Notes:
hashmap
Solutions:
3576. Transform Array to All Equal Elements
Problem Summary:
We have an array of -1 and 1. We can perform an operation to flip two adjacent numbers. If we can make at most K operations, can we make the entire array equal?
Notes:
Just greedily attempt both all positive and all negative
Solutions:
3584. Maximum Product of First and Last Elements of a Subsequence
Problem Summary:
Find the maximum product of the first and last elements of any subsequence of nums, subsequence size m. N M = 1e5, A[i] between -1e5 and 1e5
Notes:
We can do postfix mins and maxes and scan, and check a distance of M away
Solutions:
3583. Count Special Triplets
Problem Summary:
Find the # of indices triplets where the middle is half of the outer edges.
Notes:
Use a prefix and suffix and scan for O(n)
Solutions:
3582. Generate Tag for Video Caption
Notes:
Basic string manipulation
Solutions:
3581. Count Odd Letters from Number
Notes:
Basic counting question
Solutions:
3659. Partition Array Into K-Distinct Groups
Problem Summary:
We have numbers, N, A[i] <= 1e5, can we split them into groups of size K where every element in each group is distinct?
Notes:
First, make sure the most frequent number occurs <= groups times (otherwise it is impossible) and also make sure n % k == 0. Imagine the frequency of our numbers is like a histogram, taller bar means a more frequent element. O OOO OOOO Frequencies are [1, 2, 2, 3]. Say we are trying to make 4 groups of size 2. The slots will look like this. X|X|X|X X|X|X|X Simply lay the most frequent element (3) into three groups: X|X|X|X O|O|O|X Now lay the next most frequent (2). Here I use lowercase o to show the second layering. o|X|X|X O|O|O|o And repeat. Of course we can fill out all the slots, because no frequency is >4.
Drill Type:
MindsolveMindsolve and review the notes
Solutions:
3658. GCD of Odd and Even Sums
Problem Summary:
Find the GCD of the sum of the first half and sum of second half of odd and even numbers.
Notes:
Could even use math to get the sums from 1...n and get their GCD, O(1)
Solutions:
Planets Queries I
Problem Summary:
You have N planets each has a teleporter to some other planet. We have Q queries where we teleport up to K times. Which planet do you end up on? N,Q <= 2e5. K <= 1e9.
Notes:
Binary lifting
Drill Type:
ImplementImplement a solution
Solutions:
1700. Number of Students Unable to Eat Lunch
Problem Summary:
A cafe serves 2 types of food. Students stand in a queue and each wants a specific type. Foods are placed in a stack and students either take from the top of the stack or loop to the back of the line. How many students cannot eat?
Notes:
We can simulate which is slow but the constraint is small, but with higher constraints there is probably a better way I didn't look. Not really a queue / stack problem also (at least the easy solution)
Solutions:
1701. Average Waiting Time
Problem Summary:
A chef cooks for customers arriving at different [L, R] times, he cooks in arrival order, what is the average waiting time?
Notes:
We can just simulate and count it
Solutions:
1704. Determine if String Halves Are Alike
Problem Summary:
Does the first half and second half have the same number of vowels
Solutions:
1706. Where Will the Ball Fall
Problem Summary:
We have a 2d grid and we drop balls, it's like plinko sort of (see picture). For each starting location at the top where does it fall.
Notes:
I used dp(row, column, quadrant in square, moves at this row). Moves at this row prevents us from cycling back and forth forever.
Drill Type:
Implementsolve it
Solutions:
1708. Largest Subarray Length K
Problem Summary:
An array "A" is considered "larger" than another if the first index they differ at, "A" has a bigger element. Find the largest subarray of length K for an array where every number is distinct.
Notes:
Scan left to right making room for the full subarray of length K, keep checking the biggest number as the start and use that
Solutions:
Two Sets
Problem Summary:
Given a number n, we have 1, 2, 3, ... n. Partition into 2 sets of equal sum and print them, or determine not possible
Notes:
Keep taking from the left until we overflow, then subtract We are guaranteed to be able to make all sums of 1 using just 1 So when we add a 2, we can make 2, and all previous sums added (up to 3) Now when we add 3, we can add it to all previous ranges, so up to 6, and so on Eventually we will overflow the target by some amount < the number we just added at the end, so we can remove that single number
Drill Type:
MindsolveMindsolve this
Solutions:
C2. Pokémon Army (hard version)
Problem Summary:
Given an array of numbers, A[i] <= 1e5, N <= 3e5, and Q queries, Q <= 3e5, support point updates and find the largest alternating subsequence sum A + B - C + ... The input array is a permutation.
Notes:
A segment tree where each node stores the largest sum where the first and last elements were added, added and subtracted, subtracted and added, and both subtracted. Note the subtracted then subtracted base case for a leaf node is -1 * value, not NINF. There is another perceptive solution. Given the input is a permutation all numbers are local maximums or local minimum (bigger or smaller than both neighbors, ends of the array count as -inf). The length of our sequence should logically be even. Odd index should always be local maximums, if not, it implies there is an adjacent neighbor bigger, we should take that instead. If we had an odd index not be a local max we could basically take its adjacent neighbor instead as an odd index and gain more. If that neighbor were an even index we should delete that and our current odd index to not lose to our contribution (need to think about this more). But essentially all local maxes and local mins should be taken. (also need to think about this). And to support swaps we can do bookkeeping on this.
Drill Type:
MindsolveRemember this application of segment tree, also stay vaguely aware of the local maximum and minimum idea
Solutions:
D. Rescue Nibel!
Problem Summary:
We have N ranges [L, R]. N <= 3e5 R <= 1e9. We need to select K ranges that all overlap, how many ways can we do this? K <= 3e5.
Notes:
First note trying to pick a range and see how many ranges touch that, doesn't work, as if two ranges touch our selected range, that doesn't mean those 2 overlap. Instead we go by coordinate point, starting left to right. We can pick some amount of ranges that already started, but need at least 1 new range starting here to avoid double counting. We can try taking 2 ranges starting here, 3, and so on, as it amortizes. Combinatorics. We pop from a heap or multiset on the left as well as we slide, for ranges that already ended.
Drill Type:
MindsolveMindsolve this
Solutions:
C1. Pokémon Army (easy version)
Problem Summary:
Find the largest alternating sum subsequence (A - B + C - D ...)
Notes:
Standard DP I used bottom up
Solutions:
B. Rock and Lever
Problem Summary:
Find the # of pairs of numbers where the bitwise AND is >= their bitwise XOR.
Notes:
Two numbers have a max set bit. If they are the same, the AND is bigger, if they are different, the XOR is bigger. Store these counts in a frequency table and update as you iterate.
Solutions:
A. Cubes Sorting
Problem Summary:
We have an array and need to make it mono-increasing, in an operation we can swap two adjacent elements, can we make the min # of swaps < n*(n-1)/2?
Notes:
First note every element needs to swap past the # of elements bigger on its left. We could compute this with a variety of things (I used a cursed dynamic segment tree lol), but also note worst case is exactly n*(n-1)/2 in a decreasing array so we can just check that condition. Also the # of elements bigger on the left CANNOT be counted with a monostack. Not listing dyn seg tree or coordinate compression since they are so out there.
Solutions:
B. Interesting Array
Problem Summary:
We have to construct an array of size N that adheres to M requirements. Each requirement is the bitwise AND of arr[l:r] = some given and value. Return the array or impossible.
Notes:
For every element in a query range all the AND bits need to be set at a minimum, so set those. Note setting more bits cannot help do anything since it wouldn't help meet more requirements, so that is not required. We can then check the feasibility with a sparse table on the ANDs. To apply the AND bits I used a sweep line of size LOG * n. Could do lazy seg to set ANDs and normal SEG to query AND too.
Solutions:
Ferris Wheel
Problem Summary:
We have people with different weights, a gondola has a max weight and can seat 1 or 2 people, how many do we need?
Notes:
Sort and two pointers from the end. Always try to pair highest weight with lowest, don't need to try to pair with a bigger low, because we aren't "saving room" for another high weight as we are using the highest.
Solutions:
Apartments
Problem Summary:
We have apartments of different sizes and people who want to live in apartments of given sizes, but accept a threshold difference of K, how many people get apartments?
Notes:
Sort both arrays and greedily assign with two pointers
Solutions:
Movie Festival II
Problem Summary:
We have movies with [L, R] times and K people. How many can we watch?
Notes:
First thought might be store a heap of R (ending times of people currently watching movies), sort movies by R, and when we get to one, pop all that are <= L. See this test: k=2 (1, 50) (1, 60) (100, 150) (40, 200) We would assign 2 people to 50 and 60, pop both for 150, but then 200 we cannot actually attend. Sorting by L doesn't work either because we cannot determine if this L is worth watching or if we should save it. Instead imagine K lanes of people, we sort by R to greedily consume early and assign the range to the latest ending time that is <= L. I sorted by R and if there is a tie on R it doesn't matter, because we will assign to the largest ending that is free, so any order works. I don't think another sort works (like if tie R, always put the leftmost L first and then assign that interval to the smallest last, instead of the biggest last that is <= L, because a further bigger R+1 or something might demand a small L that we filled up).
Drill Type:
Implementremember the idea and read notes and implement
Solutions:
Traffic Lights
Problem Summary:
We have a road from 0...x and every second we turn on a light at one point in the road, what is the longest passage of unlit area after each point? Note the lights operate in ranges, so if we have [0, 1, 2, 3] and we turn on 0 and 2, 0-2 is still a valid unlit passage.
Notes:
First we can use a sparse seg tree with point lights and range "longest contiguous range of 0s" by storing pref, suff, max, width inside the lazy nodes. A lot of lessons with lazy node practice such as create two children every time such as in pointUpdate, how to use pointers safely, and don't store nodes in a vector it is so easy to make bugs. Also in the pointUpdate function for a sparse seg tree as we descend and create nodes, we can create random dummy values see this python solution (TLE): https://cses.fi/problemset/result/15936995/ because as we recurse down those nodes will pull anyway. But the child we don't recurse to in a point update has to be made correct since we will pull on it. With a vector of nodes and each node has indices pointers it was so hard, pushing to a vector and doing Node& node = tree[i] causes issues because the tree vector resizes and tree[i] diverges from the node. Inside a pull of sparse seg tree since we already have the node we should update the values of the node directly to keep parent pointers that point down to us. Okay now for the query this is one of those weird point vs range index tricks. If we have 0 1 2 3 (4) 5 (6) 7 where () means it is lit, our longest path is 4 from 0-4. Even if 4 is lit. There's some edge cases with boundaries being lit and whatnot too. But my point is we cannot just take the longest range of unset points and add 1 to get the longest range. Like the 5 area has an unlit passage of 2 because its boundaries are lit, but the 7 has an unlit passage of 1 since it is at the edge. Easiest implementation is to light 0 and x at the start and everything works. I also did a multiset interval tree style solution but instead of storing ranges we just store the cuts, it makes the implementation easy and is good practice. Also I think we could do a dense segment tree with compression but it seems difficult to manage the widths of things.
Drill Type:
ImplementImplement a sparse seg tree (tricky thing around the pointRecurse function), use pointers in C++ for the seg tree, and remember the point versus span weirdness in this question, also implement the interval tree inverted
Solutions:
Collecting Numbers II
Problem Summary:
We have a permutation and will scan left to right, picking up numbers in order. We have M swaps where we swap position A with B. After each swap, report the # of scans needed to collect all numbers.
Notes:
Any time a number is after its next number, so [6, 1, 5] 6->5 is inverted we would require another scan. We can track this with bookkeeping. Remember to make each query [L, R] ordered as I had a bug.
Solutions:
Tree Matching
Problem Summary:
A matching of edges is one where each node touches at most 1 edge. Find the max # of edges in a matching.
Notes:
Use greedy, dfs returns (edgesUsed, isRootTouchingEdge). We can connect to a child if any child wasn't part of an edge. Watch for tricks to check a leaf in C++ using dfs(node, parent), we cannot just check g[node].size() == 1 since node could be the root. Also a base case where we have one child is not sufficient since that child could have more leaves.
Solutions:
Tree Distances I
Problem Summary:
find the max distance to another node for all nodes
Notes:
Tree rerooting DP. First compute the answer for a max dist below for all nodes, when rooted at 0. Next we reroot. Iterate over adjacent children to solve for them. The max distance for a child is either its down distance (computed in dfs 1), 1 + max distance going up from our node (we will maintain an up array we solve for in dfs2), or 1 + max distance going down, from our node, but not going through this child. To compute that we need the best 2 downward paths (computed in step 1).
Drill Type:
ImplementSolve with reroot Drill 1: 4/22/26 Solved with up[node] and down2[node] (stores 2 best), but super annoying: https://cses.fi/problemset/result/16978874/ Solved with prefix + suffix to exclude, such a great idea! 1/ we should use children instead of adj map, as adj map with prefixes makes annoying indices 2/ also remember we may set res[node] at the root level call, not in the children loop, general point not just prefix/suffix version, otherwise we never set res of the root https://cses.fi/problemset/result/16979440/ But we could also do it with res[child], I think it depends on if we use full or up, for instance we seed full[0] here and update in child https://leetcode.com/problems/count-number-of-possible-root-nodes/submissions/1985506557/ point is BE FLEXIBLE We can also do it by tracking the best node distance or something, so like solution 1 but we bookkeep the best node to help dedupe EDIT: I did that in 2538. Difference Between Maximum and Minimum Price Sum and added a mindsolve for it, the idea is for a node we track the best child we passed through, found it easier to implement
Solutions:
Tree Distances II
Problem Summary:
for each node in a tree, find the sum of distances to all other nodes
Notes:
First compute the size of a subtree for all nodes (root at 0) and then we can get the distance to all nodes below us too. The root 0 would then be the distance to all other nodes. To transition we run a second dfs, iterate over children of a node. The child answer is the parents answer but all nodes in the child subtree moved 1 closer and all other nodes 1 further.
Drill Type:
ImplementImplement reroot dp
Solutions:
Hotel Queries
Problem Summary:
support point update and query leftmost >= X
Notes:
use a max seg tree and walk, could use sqrt decomp technically
Drill Type:
ImplementImplement the seg tree walk
Solutions:
Distinct Values Queries II
Problem Summary:
Support point updates and range queries [L, R] "are all numbers distinct"
Notes:
We can keep a next[i] array which points to the next occurence of that number or N if no further ones. Build a range min seg tree on this. If the min is > R, all distinct. To support updates we need sorted containers of indices to do bookkeeping. We could also compute # distinct with a merge sort tree on the nxt pointers, find how many values are >R in a range. I think fractional cascading could speed up the merge sort tree when using vectors, and I think order statistic containers could allow updates but not sure... Tin said there is a 2d structure like a fenwick tree on a persistent segment tree not even going to tag this. He said you can range set and count distinct too.
Drill Type:
ImplementImplement this nightmare
Solutions:
Distinct Values Queries
Problem Summary:
Support offline [L, R] distinct # of values queries
Notes:
Mo's to sort queries. A hashmap to track frequencies as we slide TLEs due to constant factor inside the hot path. Instead, we compress values to positions and store them in an array, compressed[i] is just the compressed index of arr[i]. We maintain an active count field and increment or decrement as we hit 0 or 1 frequencies. This constant optimization passes. Also when we do Mo's we should expand the boundaries both first, otherwise l could pass r and we start subtracting elements from the range. This would be un-done when we expand r, but bookkeeping (for instance checking things have frequency 0 and deleting them from a hashmap) might get bugged. We can also support online queries in logN with a persistent segment tree. We could also get num distinct with a merge sort tree on nxt[i] pointers and search how many values are >R. I think fractional cascading can speed this up. I think we could even support updates if using order statistic containers. We could also do offline scanning weirdness: Make a first[i] array which is 1 if it is the first occurrence of an number, otherwise 0. Sort queries by L. As we increment L we lose numbers out the left, we need to update inside our window any first occurrence of a number inside that window (can be done with nxt array bookkeeping). To get the # of first elements in our window use fenwick tree diffing to query sum l...r
Drill Type:
ImplementJust implement mo's smoothly along with the other needed optimizations
Solutions:
3762. Minimum Operations to Equalize Subarrays
Problem Summary:
Support range queries [L, R]. Given an operation where we can change A[i] by +-k, find minimum # of operations in a range to make every number equal, or -1 if not possible.
Notes:
If all numbers in a range do not have the same remainder mod K, it is not doable. We could make a remainder array and compare the max and min with a sparse table, or many other solutions (Mo's + max/min using two-stacks trick or monodeque, Mo's + hashmap of unique values, # of distinct elements query online or offline on a remainder array, etc). Now we need to find the median and sum of elements <= median and sum >= median and set everything to the median. First, we can use sliding window multisets with Mo's but it is O(n * rootN * logN) and TLEs because of overhead. We can use Mo's + fenwick/seg tree which is O(n * rootN * logN) but it passed with some optimizations. Here are some notes: -Fenwick or seg tree can store values not indices, and we update and remove values as we slide. We need to find the k-th element (can store counts in a node and do a tree walk) to find the median. And the sum of the first k elements if we store sums in nodes. We could also support queries like sum of numbers from [lowerBound, higherBound] by diffing prefixes or using a seg tree. Also we need to coordinate compress we can compress all array values and then use binary search on query values to find the nearest compressed array value, or compress both. Basically a few ways to do things. To AC I used optimizations: -Hilberts -Fenwicks instead of seg tree -Find the k-th element (median) and then sum of the first K, then use O(1) to get the top half sum and count so we only do 2 log operations per Mo. We can also use online range query for median and online range query sum <= median using persistent seg tree for n log n. Tin has some sqrt decomp code that seems to support point updates, range median queries, and range sum queries for l...r in a value range x <= ? <= y too, but not sure how this works: https://leetcode.com/problems/minimum-operations-to-equalize-subarrays/submissions/1844480184/ I bet we can do a merge sort tree with prefix sums too or something crazy.
Drill Type:
ImplementImplement something and also read through notes and different ideas
Solutions:
F. Range Update Point Query
Problem Summary:
Support range update "replace every number with the sum of its digits" and point query
Notes:
I did it with a lazy seg tree where we have a lazy amount of operations applied. To point query we can reconcile the lazy updates by applying them, breaking early if our number ends < 10. Note this only works for point queries but range sum queries don't really work cause we cannot reduce a range sum like that, [50, 50] has total sum 100 which would become 1, but if we updated each 50 individually we should get 5+5=10 I think we can also do a normal seg tree where the range update is A[L] += 1 and A[R+1] -= 1 and we query for the total in a prefix, since we do point queries. Also since a given number can only be updated 3 times we could just track living numbers in sorted containers. Probably other solutions.
Drill Type:
MindsolveRemember the normal seg tree version
Solutions:
Coin Piles
Problem Summary:
we have two piles of coins, we can remove [1, 2] or [2, 1] from them, can we empty them at the same time?
Notes:
if the total is not divisible by 3, no. If the max is > 2 * min, no. Otherwise, we can equalize their sums. And then take away [3, 3] in sets of 2 moves.
Solutions:
Bit Strings
Problem Summary:
compute 2^n % MOD
Solutions:
Tree Diameter
Problem Summary:
Find the max diameter of a tree
Notes:
Rooted at 0, a max diameter must pass through some LCA, so for each node do a tree convolution on the longest chains to update the result
Drill Type:
MindsolveQuick mental refresh
Solutions:
Minimal Grid Path
Problem Summary:
Given a grid of letters, find the lexicographical smallest string to go from top left to bottom right, only moving down or right.
Notes:
DP is n^3 because we need to compare strings at every cell. There is a cursed way to get n^2 log N. For instance say we are computing the smallest string to reach r,c, it is either r-1,c + newLetter or r,c-1 + newLetter. We need to know which of those is shorter. Instead of holding the entire smallest string for those, we could set up dynamic binary lifting on a nodes best choice, so maybe r-1,c had a best choice to go to r-2,c. We need to assess the prefix hashes of some path going from 0,0 to r-1,c and 0,0 to r,c-1 to find the longest common prefix to be able to find which letter they differ at, along the optimal paths, to find which path was lexicographically shorter. I think binary search + binary lifting gives n^2 log^2n but there should be a way to get just n^2 log n according to chatgpt. The better way is just a frontier. We store a list of the current frontier positions and check all down and right positions, keeping only a new frontier with the minimum letter. n^2.
Solutions:
Palindrome Queries
Problem Summary:
support point character updates and range is palindrome queries
Notes:
Good practice for understanding forward hash and rev hash for s[l:r] substrings In the seg tree we need to shifts hashes by a certain amount when merging nodes. In the query function we are essentially merging new nodes we create on the fly. If we pass ql and qr down to queries, things will get messed up with the widths. A child seg tree node with range [0, 4] for a query [2, 7] will merge two children, but when we merge children we cannot do say qr - (tm + 1) + 1 for the right width because the right merge is probably like [3, 4] or something and has width 2. We can either cap the widths as pictured below (no need to do it in the recursive calls), or just store a width on the Node struct and merge that (easier) Node _query(int i, int tl, int tr, int ql, int qr) { // if we are fully in range, return our node if (ql <= tl && qr >= tr) { return tree[i]; } int tm = (tl + tr) / 2; // If only the left is in range return that if (qr <= tm) { return _query(2 * i, tl, tm, ql, qr); } // If only the right is in range return that if (ql >= tm + 1) { return _query(2 * i + 1, tm + 1, tr, ql, qr); } // we need to merge both Node left = _query(2 * i, tl, tm, ql, qr); Node right = _query(2 * i + 1, tm + 1, tr, ql, qr); int leftWidth = min(qr, tm) - max(ql, tl) + 1; int rightWidth = min(qr, tr) - max(ql, tm + 1) + 1; return merge(left, right, leftWidth, rightWidth); }
Drill Type:
ImplementGood luck
Solutions:
Subordinates
Problem Summary:
print the size of all subtrees
Solutions:
Forest Queries
Problem Summary:
Support 2d range sum queries
Notes:
Standard 2d prefix / suffix
Drill Type:
ImplementJust staying sharp
Solutions:
Range Updates and Sums
Problem Summary:
Support range assign, range add, and range sum queries
Notes:
Not listing sqrt decomp. This is a lesson in how to cleanly implement a lazy segment tree. Some invariants: 1/ If a node has a lazy tag, it implies it has already been applied to this node. Why? Supposedly makes it a bit easier to code and tin_le once had a bug without doing it this way (though I think you can do it where the tag means we still need to apply it). 2/ We should push down tags in everything (queries, updates) instead of just queries. I believe in theory we only would need to push down tags in queries for some problems, like support range add and range sum. For instance if we range add to the entire tree we put a tag at root then if we range add to a leaf we could put a tag at the leaf (without pushing down the root) then when we query we push and aggregate. But I think for more complex problems like this one we might need to push updates every function (not sure) but either way it feels easier and more logical to do so. 3/ Push is really: apply this tag to children, then update their lazy tags by composing. "pushDownLaziesAndClearCurrentLazies" 4/ Pull is just update the current node based on freshly updated children
Drill Type:
ImplementRead notes and practice implementation
Solutions:
F. Cherry Tree
Problem Summary:
The leaves of a tree each have a cherry. We can shake a subtree to remove all cherries in it, but if you shake a leaf that already dropped the cherry the tree broke. Can we clear all cherries with a # of shakes divisible by 3?
Notes:
Standard tree convolution where we look at children and merge them together, however the implementation is a bit more unintuitive here. For instance we normally have a beforeChild and afterChild state and we initialize beforeChild to an identity value, but the identity in this problem was confusing: [True, False, False] meaning we can clear all cherries in this tree with a remainder of 0 shakes. This is vacuously true. Because when we consider just the root node as the tree (before any children) we don't have any leaves inside yet and thus can clear this empty tree. To aggregate, we need to clear the new LHS + RHS and can update newDp[0] [1] and [2]. I ended up implementing it with no identity value and starting my beforeChild dp on the first node, and looping through the second and further node. To merge in the children we do need to update newDp[1] and this isn't considering the chance we can shake the entire subtree at the root. That is more of an edge case that can be done after and we always update newDp[1] at the very end. There is also a second editorial solution I didn't understand I ended up trying this a bit later in C++ and still felt it easier to establish a base case for a leaf, and use the first child as part of the DP, and loop over the second and later children: https://codeforces.com/contest/2184/submission/359466005
Drill Type:
ImplementI should understand the idea of the identity value in tree convolution and what the exact meaning of the states for before and after child mean for this problem, and how shaking the entire tree is unrelated to the convolution
Solutions:
Hidden Integer
Problem Summary:
basic interactive problem that is binary search
Solutions:
Visible Buildings Queries
Problem Summary:
We have buildings with heights, standing from the left we can see only a certain amount due to their heights. Given Q queries [a, b], if only buildings in [a:b] existed, how many buildings could we see?
Notes:
First for each index compute the next greater index. I pushed MAX_HEIGHT+1 to the end to make it easy. Then build binary lifting where jump[power][index] tells us the next index we can go to, or jump[power][sentinel] points to itself to make us able to index into the jump tables easily without if/else branching. Now we can answer queries.
Drill Type:
Implementgood to practice implementation
Solutions:
Longest Common Subsequence
Problem Summary:
Find the length of the LCS and reconstruct it
Notes:
Should practice: Bottom up pull dp + recon Bottom up push dp + recon Top down dp + recon A lot of lessons here: Say we build dp[i][j] to represent the LCS for ...i-1 ...j-1. Then the answer is dp[n][m]. I did this with push dp, but I could do dp[i][j] represents LCS for ...i ...j with pull DP. Note we can dp push / pull dp with both representations of ...i ...j or ...i-1 ...j-1. We may need if/else branching to handle out of bounds in different cases. Once we finish the DP, we need to reconstruct. We could try to walk forwards from 0,0, but it will not work. Visualize this: file:///Users/ishaan/Desktop/Screenshot%202026-01-12%20at%2012.42.09%E2%80%AFAM.png If A[i] and B[j] match sure we should always walk that diagonal to try to construct the path covering the most diagonals, but if they do not match, we don't know which way to turn. Analyzing dp[i+1][j] and dp[i][j+1] tells us nothing because that is information about PREFIXES, the most diagonals we can get reaching that cell. We need suffix info. If we build our dp to be suffixes i... j... we could "walk forwards" but really that is walking backwards in reverse. So instead, we start at the bottom right and if we can go up-left to a diagonal we always should. Otherwise, we will pick the best prefix result. This is essentially how top down works because dp(i, j) is SUFFIX information so even if it feels like we are constructing forwards when we do top down, we are not. We could also just do our bottom up DP as a suffix then "build forwards" (really it is backwards). In pull dp bottom up where dp[i][j] represents ...i ...j inclusive, if A[i] == B[j] in theory our best path can always take i-1 j-1 diagonal and we don't need to pull in i-1 or j as options. Same with push DP (with ...i-1 ...j-1 in this example), I think, if A[i] == B[j] we should only need to push dp[i+1][j+1] and not bother updating dp[i][j+1] or dp[i+1][j], but the reconstruction fails if we try to put those other 2 updates inside an else branch. Why? See this example: [1, 2, 2] [1, 2] The dp is: 0 0 0 0 1 0 0 0 2 0 0 2 So at our bottom right, we could go up-left for a valid LCS based on the sequences, and we attempt to in our reconstruction, but when we filled the DP table we did not produce the LCS with those steps because we skipped cells, so we mess up our reconstruction. And it did that because at the 1 we only pushed to down-right instead of down also, due to shortcut. The best lesson here is to just enumerate all edges in both push and pull DP. Even if we can skip and take shortcuts without affecting the final dp[-1][-1], if we don't take our shortcuts, then every dp cell is filled our accurately which is nice.
Drill Type:
ImplementRead notes, practice implementations
Solutions:
Writing Numbers
Problem Summary:
We are given N <= 1e18, we can write each digit N times, find the largest number we can write in a sequence 1, 2, 3, ...
Notes:
Binary search on the answer, use digit dp to calculate the # of ones used to write 1, 2, 3, ... that number. 1 will always be used up first. Can do dp(i, tight) and return (numOnes, numWays) or dp(i, tight, onesUsed). We can also use math for each digit, digits go in cycles, like the tens digit is 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 ... so we can compute full cycles and partial cycles and add up the contributions
Solutions:
Swap Game
Problem Summary:
given a 3x3 board we can make orthogonal swaps, construct 1 2 3 4 5 6 7 8 9 in order
Notes:
just do bfs, we can do it with numbers by swapping two digits, to grab a digit from the middle floor divide the number and mod 10
Drill Type:
MindsolveJust quickly refresh how to mathematically extract a digit from the middle of a number
Solutions:
Range Update Queries
Problem Summary:
support range addition and point queries
Notes:
can just use a normal segment tree on a diff array, an update is diff[L] += X and diff[R+1] -= X, not listing other methods like sqrt decomp
Solutions:
Counting Bits
Problem Summary:
Count the # of set bits in all numbers from 1 to N, N <= 1e15
Notes:
can use digit DP in two ways, dp(i, tight, onesUsed) or dp(i, tight) which returns (numWays, numOnes). cannot use a global res in the DP (see code) -can also use bit operations math, write out bits: 0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 8 1000 9 1001 10 1010 11 1011 12 1100 13 1101 14 1110 15 1111 For a given bit position, it goes in cycles like 0 0 1 1 0 0 1 1 so we can, for each bit, see how many full cycles + partials it would contribute
Drill Type:
MindsolveReread notes
Solutions:
Sliding Window Cost
Problem Summary:
For each window of size k, find the cost to change all elements to be the same (cost is abs(newVal-oldVal))
Notes:
-Sliding window with median using two sorted containers or heaps works -Maintain the sum of each window bucket too to calculate the cost to change both halves into the median Can do online with persistent segment tree somehow
Drill Type:
ImplementPractice two sorted structures rebalancing
Solutions:
Sliding Window Median
Problem Summary:
Find the median for all windows of size K
Notes:
-Can use persistent segment tree for online (I think) -Can use two lazy heaps with rebalancing but the implementation is a bit tricky -Can use two multisets with rebalancing The invariant is that we should always add a node to the correct upper or lower half of the datastructure, don't just add it randomly. Then rebalance() just rebalances sizes only, it doesn't worry about fixing incorrectly ordered elements
Drill Type:
ImplementPractice two buckets rebalance implementation
Solutions:
Dynamic Range Minimum Queries
Problem Summary:
support point updates and range min queries
Notes:
could do sqrt decomp not listing though
Drill Type:
ImplementBasic seg tree practice
Solutions:
Static Range Minimum Queries
Problem Summary:
answer range minimum [l, r] queries
Notes:
sparse table is best, can do seg tree and sqrt decomp and mo's -sqrt decomp online is built on indices, so each block tells us the minimum in that block, to query we scan over rootN blocks, to update we modify A[i] then recompute that blocks minimum in rootN. -we can do mo's, basic mo's is n * rootN * logN with a sorted container, or essentially n * rootN with a FastSet. We can also get O(1) transition with mo's. To do this, we compress all the values and build a sqrt decomp on values. To perform an update to our mo's window (adding a value) we increase the occurence of that by 1 in our decomp, same to decrease. So the individual freq[number] goes down by one as well as the block containing that number. To query the minimum we scan over blocks left to right until we find a block with a frequency >= 1 and scan over the numbers inside it in rootN.
Drill Type:
ImplementImplement sparse table, re-read notes for sqrt decomp
Solutions:
Static Range Sum Queries
Problem Summary:
solve static sum queries [l, r]
Notes:
standard prefix addition
Solutions:
Nearest Smaller Values
Problem Summary:
for each index, find the index of the nearest smaller number on the left
Notes:
use a monotonic stack going right to left, good practice, not listing other worse solutions
Drill Type:
ImplementBasic monostack practice
Solutions:
Distinct Values Subarrays II
Problem Summary:
Find the # of subarrays with at most k distinct values
Notes:
We can do a sliding window and answer the rightmost end for each L, a bit tricky since we loop on L first, remember r defines the candidate we are considering, not yet in the window. We could probably do some binary search range distinct values persistent seg tree n log^2 n thing too but might be too slow
Drill Type:
ImplementSolve and implement DRILL 1: Hm for some reason I wanted the rightmost end for each L before, but in this drill I was able to solve it for each R. We expand R one at a time as normal, shrink while required, and now we have the answer for that R: https://cses.fi/problemset/result/16989180/
Solutions:
Room Allocation
Problem Summary:
We have hotel customers staying at [arrival, departure] times. What is the min # of rooms to host them all? And print a valid room order.
Notes:
We greedily allocate rooms. Store a heap last[] which tells us departure times of people in the hotel. If no room is free create a new one. The heap holds (departureTime, roomUsed) to help bookkeep the available rooms.
Drill Type:
MindsolveJust mindsolve
Solutions:
Josephus Problem II
Problem Summary:
We have n people and remove the kth at a time, print the removals in order
Notes:
We can simulate it by finding the kth after our current position, the github code is a very clean implementation. We can also use a segment tree walk to for instance find the k-th 1 in a range, and point update to 0.
Drill Type:
ImplementImplement a solution and read notes
Solutions:
Josephus Problem I
Problem Summary:
We have n people and remove the 2nd person each time, print the order of who is removed
Notes:
Simple simulation. With an array we can scan left to right (cost N) but we only do this logN times as it halves. Or we can use a deque to simulate for O(n)
Solutions:
Josephus Queries
Problem Summary:
We have n people in a circle and remove the second person every operation. Who is the k-th person removed?
Notes:
Assuming we have 1-indexed people [1, 2, 3, 4, 5, 6, 7] and k=3. Obvious base case if k <= # of people removed, we return 2*k. Also if 1 person is left [1] we remove that person. // if we have an even amount of people // 1 2 3 4 5 6 7 8 // 1 3 5 7 // ^ // 1 2 3 4 // Every new person * 2 - 1 equals our old label // if we have an odd amount of people // 1 2 3 4 5 6 7, k=5, we remove 3, new k=2 // 1 3 5 7 // ^ but now this is the start // 7 1 3 5 auto oneIndexResult = solve(newPeople, newRemovalQuery); // get the normal 1 3 5 7 indexing oneIndexResult -= 1; if (oneIndexResult == 0) { oneIndexResult = newPeople; } // Now we have the index in the good sequence 1 3 5 7 // The index in our initial sequence is therefore 2 * that - 1 return 2 * oneIndexResult - 1;
Drill Type:
ImplementImplement this and read notes
Solutions:
Distinct Values Sum
Problem Summary:
Find the sum of # of distinct elements in a subarray for all subarrays
Notes:
Use contribution technique, each number contributes to a certain sum, we can go all the way to the right edge, or left up to but not including the occurrence of the same number
Drill Type:
MindsolveJust quickly gloss over code again, no stack needed for this
Solutions:
Distinct Values Splits
Problem Summary:
Find the # of distinct "splits" of an array, ways to partition the array such that no region has a duplicate
Notes:
For a given left index we can find how far right we can go while all #s are distinct, using a tricky sliding window. Then dp[i] is the sum of a suffix range of DP values.
Drill Type:
ImplementImplement this
Solutions:
Longest Palindrome
Problem Summary:
Find the longest palindrome of a string
Notes:
We can use manacher's O(n) or binary search + rolling hash. Supposedly palindromic tree can be used too.
Drill Type:
ImplementImplement binary search + rolling hash, read notes about palindromic tree
Solutions:
Distinct Subsequences
Problem Summary:
Find the # of distinct subsequences of a string of letters
Notes:
dp[i] is the number of distinct subsequences for s[i:] where we must take i. We recurse to all 26 next letters. Implemented cleanly in C++ bottom up!
Drill Type:
ImplementImplement in C++
Solutions:
Finding Periods
Problem Summary:
Given a string, find all lengths that form a period inside the string
Notes:
Use z-function, for each length, don't check every character at a time, check the z-placement and the next size, using harmonic series. Could also use rolling hash to do the check.
Drill Type:
MindsolveRe-read notes
Solutions:
Finding Borders
Problem Summary:
Given a string S, find the lengths of all prefixes that are also a suffix
Notes:
suffix array might work here but really not sure
Solutions:
String Matching
Problem Summary:
Given a pattern and a target string, find how many times it occurs.
Notes:
Can use rolling hash, aho corasick, z-function, or KMP. Z-function notes: |0 1 2 3 4 5 6 7| 8 9 10 11 12 13 14 15 16| 17 18 [indices] |a a b x a a b x| c |a a b x a a b x | a y z-box set 9-16 when we reached i=9 |0 1 0 0 4 1 0 0| 0 8 1 0 0 4? [z array] ^ now we try to solve at i=13, we are inside the z-box so we can re-use work the corresponding k is k=4, which has a z score of 4 All we are saying is the z-box perfectly equals our prefix, and so we can use some of that work. We know the letter after the z-box ending doesn't equal the letter after the prefix (index 17 doesn't equal index 8) but if we try to re-use work for index 13, it doesn't mean index 17 cannot match index 4. Also the reason we do z[i] = min(r - i + 1, z[k]) is literally all we have is the guarantee the prefix equals the z-box. We don't know if any letters past match even if z[k] is really big because we don't know if our z-box right edge would keep matching the prefix. Note if we started our for i loop at 0, we would initialize the z-box to 0:n-1 z[i] to n. Then for all future i we are inside the z-box and set z[i] to be 0 initially (set equal to z[k], which is the same as z[i], ends up being 0). Now nxt and pref are messed up and we loop fully inside n again. Also if z[k] ends up being less than r-i+1, we don't need the future nxt/pref code, we can just continue immediately in theory, since z[i] could never be greater (see github code)
Solutions:
Word Combinations
Problem Summary:
Given a target string <= 5000, and K words (sum length K <= 1e6), find how many ways we can build the target.
Notes:
Naive dp is dp(index) and we loop on future j to see if target[index:j+1] is one of the words, if so add on the next DP. This can use rolling hash or trie to O(1) check if it is a word. I did bottom up DP with a trie. I think aho corasick + dp is faster
Drill Type:
MindsolveQuick re-read notes
Solutions:
Sliding Window Minimum
Problem Summary:
Find the XOR of all window minimums of size K
Notes:
-Can use the monotonic deque strategy -Can use two stack queue -Can use prefix and suffix mins and aggregate the answer across a min of two (alex wice style) -Sparse table will tle
Drill Type:
ImplementImplement both two-stacks and monodeque, re-read wice notes
Solutions:
Sliding Window Or
Problem Summary:
Compute the bitwise XOR of all window ORs of size K. Sparse table and n*BITS solutions will TLE.
Notes:
I used the two stacks aggregate solution to get O(1) transitions on irreversible actions. We can also build blocks of size K with prefix and suffix ORs, then any window is just the aggregate of a suffix OR and a prefix OR (alex wice solution).
Solutions:
Sliding Window Mode
Problem Summary:
Find the mode for each fixed window range, if multiple pick the smallest number
Notes:
We can track number -> frequency and frequency -> sorted container of numbers with that frequency. This requires us to track a variable for the current max frequency and do extra bookkeeping. Instead, we could track number -> frequency and a sorted container of tuples (-freq, number) and the add and remove functions become very easy. There might be a segment tree on values solution here, not sure, GPT said: 1) Segment tree over values (no set, no “sorted container”) Idea: coordinate-compress the values, maintain freq[idx] for each distinct value, and a segment tree where each node stores: bestFreq in that segment bestIdx = smallest index achieving bestFreq Combine rule: pick higher bestFreq if tie, pick smaller bestIdx Then: add/remove = point update on that value’s index mode = root.bestIdx, output origValue[bestIdx] Complexity: O(n log m) where m = #distinct ≤ n), memory O(m). This is the cleanest “not using sorted containers” exact solution.
Drill Type:
MindsolveQuick re-read notes
Solutions:
Sum of Three Values
Problem Summary:
Given an array, find 3 indices with values summing to X or print impossible
Notes:
Sort then run two pointers for O(1) space
Solutions:
Sliding Window Distinct Values
Problem Summary:
for every window of size k, determine the # of unique elements
Notes:
just use a counter and measure the length of it, we can roll up all the logic into a single for loop easily
Solutions:
Sliding Window Xor
Problem Summary:
Calculate the XOR of all window XORs of a fixed size
Notes:
I simulated with a deque but we should be able to pretty easily compute how many windows an element will be a part of, and then include or not include the xor of that in the result, for O(1) space
Solutions:
Movie Festival Queries
Problem Summary:
We have N movies with start and end times [L, R]. R <= 1e6 (can be bigger, just use coordinate compression). We have queries [arrive, leave] for times we are at the theatre. How many movies can we watch per query?
Notes:
This is jump tables with implementation difficulty. First note we don't need coordinate compression since R is small. For each time, we want to know the next movie we could finish, so as small an R as possible, but L must be >= our time. I computed these with binary search but could do other methods. I used top down jump tables to help gain clarity. up(power, time) tells us the next movie time finish we are at. Base case is time = MAX_R + 1 points to itself (sentinel state) which lets us chain calls to the jump table recurrence without if/else branches. Also power=0 means we directly go to the next time we precomputed with binary search earlier. For a query, we arrive at `arrive`. Jump from large to small powers as long as our ending location is <= `leave`. The movies we watch are exactly 2^jump power.
Drill Type:
ImplementImplement C++ jump tables and re-read notes
Solutions:
Chessboard and Queens
Problem Summary:
Find the # of ways to place N queens on a board with blocked cells
Notes:
standard major + minor diagonal backtracking
Solutions:
Creating Strings
Problem Summary:
Generate all rearranged strings from an input string
Notes:
can do for loop inside backtrack (loop over letter, freq in a counter and place a letter or skip that type) or no for loop (if we skip a letter type, we must skip all)
Solutions:
Dice Probability
Problem Summary:
We roll a 6-sided die N times, what are the odds the sum is between A and B? N <= 100, B <= 6*N
Notes:
Naive solution is dp(rollNumber, currSum) with a for loop of size 6 inside. We can optimize the for loop to be O(1) with a prefix sum dp. FFT might be usable not sure.
Drill Type:
ImplementQuick implement DRILL 1 4/23/26: I was able to do bottom up really optimized, dp[tot] is the chance we make that amount after some number of rolls, I looped on rolls then the new total, and I maintained a sliding window sum of the dp, didn't even need prefix queries: https://cses.fi/problemset/result/16989259/
Solutions:
Inverse Inversions
Problem Summary:
We need to make a permutation of size n with k inversions, or show it is impossible
Notes:
Start with the biggest number, we can choose how many inversions include this number. Take as many as possible. Keep repeating until we hit our target. Place the remaining numbers in order. We can always satisfy the requirements.
Drill Type:
MindsolveRead solution
Solutions:
Sliding Window Sum
Problem Summary:
find the xor of all window sums of size k, large inputs
Notes:
O(k) memory to track last values, can use a deque or a ring buffer, could use O(n) memory for prefix/suffix but probably not intended
Solutions:
Shortest Subsequence
Problem Summary:
Given a DNA string, find the shortest subsequence not present
Notes:
Greedily pick the rightmost letter each time and increment a pointer, I had a clean implementation. Just remember nxt[index][letterType] should not be allowed to pick index, we need to only look at indices > index Imagine we have ACGTACGT, we first pick T, and then T again (technically doesn't matter), but we need to do j>i not j>=i to allow jumping to the same letter
Solutions:
Course Schedule
Problem Summary:
we have courses that are prereqs of other courses, print an order we can take them, or indicate if impossible
Notes:
I did kahn's where if A must be taken before B we have an edge from A->B and we track in-degrees. We could also track out-degrees and start at nodes with no out-degree on the normal graph (B points to A this time), but we need a reverse edge list to go back up anyway, so the first way is better. We can also use dfs to topo sort.
Drill Type:
ImplementImplement kahn's, re-read notes
Solutions:
Restaurant Customers
Problem Summary:
Given restaurant visits with [L, R] how many max customers will be dining at a time? Assume all L and R are distinct. R <= 1e9
Notes:
-sparse seg tree with range add and range max -normal seg tree with coordinate compression -sweep line with coordinate compression -sweep line with event sorting -sort ranges by left edge, consume each left edge at a time, but pop smallest right edges from a heap while they don't overlap (or use sorted container but won't list, heap feels more apt)
Solutions:
Movie Festival
Problem Summary:
There are movies with [start, finish] times, how many can we watch?
Notes:
Sort by right edge, track previous right border. As soon as a left is is >= previous right, greedily take this movie and update the right edge. could also do cursed solutions like dp(movieIndex) and we take or skip and binary search, but skipping these weird solutions in the tags
Drill Type:
MindsolveFast mindsolve + read notes
Solutions:
Prefix Sum Queries
Problem Summary:
support point updates and max prefix sum range queries
Notes:
standard seg tree where a node stores total sum and max prefix. skipping sqrt decomp as a solution in tags
Solutions:
Maximum Subarray Sum
Problem Summary:
find the max non empty subarray sum
Notes:
Two ways to write: curr = 0 res = float('-inf') for v in A: res = max(res, curr + v) curr = max(0, curr + v) print(res) OR: res = -inf currMax = -inf for v in nums: currMax = fmax(currMax + v, v) res = fmax(res, currMax) return res
Drill Type:
ImplementSolve + read notes
Solutions:
Stick Lengths
Problem Summary:
we have sticks of different lengths, we can modify a length by X for cost X, find min cost to make everything even.
Notes:
Say Y is the ideal cost. If Y were not the median, we could move it 1 closer to the median (say Y was too big). Now more than half the numbers would drop a cost, and less than half would gain a cost, so any value that is not the median could be improved.
Solutions:
Subarray Divisibility
Problem Summary:
find the # of arrays with a sum divisible by N
Notes:
standard lop off with remainders
Solutions:
Reachable Nodes
Problem Summary:
For each node in a DAG, find how many nodes it can reach
Notes:
We cannot sum up reachable nodes among children because children can reach the same node. Instead we maintain bitsets for what a child can reach, and OR them together. This is easy to do top-down (it shouldn't even be DP, this is just toposort with DFS). I implemented bottom up "dp" with kahn's.
Drill Type:
MindsolveMindsolve, review code and notes
Solutions:
Nearest Shops
Problem Summary:
Given an undirected unweighted graph, some nodes have a shop. Compute the nearest distance to ANOTHER shop for all nodes.
Notes:
For nodes that don't have a shop, it is a simple multi-source bfs. For nodes with a shop, we use voronoi partioning. Multi-source BFS but also stored an array claimed[node] is the region that shop claims as the closest. We can put tuples in the queue (currNode, srcNode) or just read from the array (probably better style). Now scan all edges, say we have: X-Y-Z and X and Z have shops. Say the voronoi partition ends up like X | Y Z. When we scan the X-Y edge we see the claimed array for X is different from Y, so claimed[X] borders claimed[Y] and is a candidate for the nearest shop. We can use this to help compute answers for nodes that contain shops. I did my multisource BFS with a seen array, a queue, a length = len(q) variable, a minDist array, and a claimed array, but we could just use a minDist array, a queue, and a claimed array if we write updates when we see a neighbor node, not when we pop. I think this was a cleaner way to do BFS that I never did.
Drill Type:
MindsolveRe-read notes, look at code
Solutions:
Creating Strings II
Problem Summary:
Find how many ways we can reorder a string to get a new string
Notes:
its n! / c1! * c2! * ... 2 proofs: 1/ We could start with a single character frequency, there are V0 occurrences and we have 1 string Insert V1 occurrences of the next character, there are V0 slots, so V0 choose V1. Now (V0+V1) choose V2. These multiply together. It ends up simplifying to the final n! / c1! * c2! * ... fornula Proof 2: Normally n! permutations if characters are distinct. For a given setup, we have to divide by each character independent c! since the order of those doesn't matter
Drill Type:
MindsolveRe-read math proof
Solutions:
Binomial Coefficients
Problem Summary:
compute many queries of n choose k % MOD
Notes:
Remember these are like binomial coefficients, when we do (x+y)^4 that is: (x+y)^4=(x+y)(x+y)(x+y)(x+y) In this sum of terms, we would get x^3 * y, but what is the coefficient? its 4 choose 3 (we choose x from three of the terms).
Drill Type:
ImplementRe-read idea about binomial coefficients and implement the code (especially invFact)
Solutions:
Candy Lottery
Problem Summary:
each of N children gets 1 to K candies, compute the expected max
Notes:
Solution 1 Compute the exact change max=X for all X and take their weighted sums First, compute chance of a max being 1 From this, we compute chance of maximum being at most 2 We can compute the chance max is exactly 2 by subtracting. Repeat this Solution 2 Define indicators, I1 = chance max is >= 1, I2 = chance max is >= 2, etc Now when max is X, we score I1 + I2 + ... + IX So we need to compute the expected sum of the indicators Each indicator has a chance of occuring and we can use linearity of expectation to get their probabilities It just uses inverse probability to compute these
Drill Type:
MindsolveRe-read notes
Solutions:
Bracket Sequences II
Problem Summary:
Given a prefix of brackets and a final sequence length variable N, find the number of well formed bracket sequences starting with that prefix.
Notes:
We have to place O open brackets and C closed brackets such that the closed surplus never exceeds `surplusOpen` O = opens to be placed C = closed to be placed R = remain (total to be placed) H = height (surplus we start at, we cannot touch -1) C - O = H # we will always drop down to height 0 at the end, so this is true Normal ways to place without the exceeding exclusion is C(R, O) Attempt a completion, say H=3 R=7 O=2 C=5 ) ) ) ) ( ( ) ^ violating index i=3 At the bad prefix, there are H+1 more closed than open, since we dropped H+1 steps At the suffix, there is 1 less closed than open (this would result in H total more closed than open, which is what we need) If we flip the prefix, there are H+1 more open than closed in the prefix, making a total of H+2 more opened than closed Computing # of bad sequences: R spots to place into Our flip increased the open brackets by H+1 O' = O + H + 1 We can prove this is bijective in a similar manner to bracket sequences I Every input completion will map to a different output, otherwise we can find two inputs that somehow map to the same output, find a differing index, and discover a contradiction Every output is mapped by an input because we could un-reverse the prefix and get a valid setup So there are C(R, O') bad sequences Final answer is C(R, 0) - C(R, O') C(R, 0) - C(R, O + H + 1) This would work even for invalid sequences, see: ( ( ( N = 4 O = -1 C = 2 R = 1 H = 3 C(1, -1) - C(1, 3) = 0 - 0 Not airtight but combinatorics should just end up as 0
Drill Type:
MindsolveRe-read notes / code honestly would implement but too obscure
Solutions:
Bracket Sequences I
Problem Summary:
Find the # of well formed bracket sequences of length N <= 1e6
Notes:
All sequences of length 2N must have N open and N closed brackets There are 2N choose N ways to construct these (place all opens somewhere, remaining ones are closed) However, we need to exclude sequences with prefixes that have more closed than open brackets, like ( ) ) ( This is sufficient to compute good bracket sequences, why? Necessary If a prefix contains more closed than open brackets, it is impossible for that closed bracket to ever be paired with something Sufficient Every prefix will have at least as many open as closed, we maintain a counter of surplus open Any time we encounter a closed bracket we will have at least 1 open bracket, and can decrement the counter Therefore every closed bracket decrements the counter by 1 and is paired with something All closed brackets will get paired with something safely and we will end up with a final surplus of 0 implying all open brackets were paired Now we need to compute the prefix-violating bracket sequences Write all bracket sequences, e.g. n=4 For each sequence, if it is bad we find the index it first has more closed than open, this prefix has 1 more closed than open bracket The suffix therefore has 1 more open than closed bracket We invert the prefix, now the total sequence has 2 more open than closed brackets, or more generally N+1 open and N-1 closed ()() ✓ (()) ✓ ()) | ( -> )(( | ( ) | ()( -> ( | ()( ) | )(( -> ( | )(( ) | )() -> ( | )() There are 2N choose N+1 of these resulting sequences. We are claiming we map a bijection to all possible resulting sequences. If a function is injective (every input maps to a unique output) and surjective (every output is mapped to by an input) then it is bijective. First show that it is injective, obviously every input has a different output. If two inputs had the same output, we can locate the different input bracket and show that it must produce two differing outputs, violating the claim. To show it is surjective, we work backwards. From 2N choose N+1 sequence (N+1 opening brackets), we can find the first prefix with more opening than closing brackets and re-invert that, producing an input with a prefix of more closing brackets than opening brackets, showing we can produce a state that maps to this. Therefore, this is bijective. So the final answer is C(2N, N) - C(2N, N - 1)
Drill Type:
MindsolveRe-read notes / code would implement but it is complex and too obscure
Solutions:
Dynamic Range Sum Queries
Problem Summary:
support point update and range sum
Notes:
not including sqrt decomp
Solutions:
Subarray Sum Queries II
Problem Summary:
compute the max subarray sum of different regions in an array
Notes:
standard seg tree (maxPrefix, maxSuffix, maxSubarraySum, totalSum), not including sqrt decomp, I think mo's could maybe do it also but not including
Solutions:
Subarray Sum Queries
Problem Summary:
compute the max subarray sum of the entire array after point updates
Notes:
standard seg tree (maxPrefix, maxSuffix, maxSubarraySum, totalSum). Since we print only the total subarray sum we can do an O(1) query for the entire tree for the reads. not including sqrt decomp
Solutions:
Tree Coin Collecting I
Problem Summary:
Some nodes have a coin on them. Given Q queries [node1, node2] find the minimum path distance from node1 -> node2 that touches a coin.
Notes:
Find dist on path with binary lifting or sparse table + euler tour, then find min dist on path to another coin (precompute values with multisource bfs). Not listing euler tour / sparse table since a lot of binary lifting problems can be solved with those anyway
Drill Type:
Implementtest your lifting skills
Solutions:
Range Xor Queries
Problem Summary:
find range xor queries offline
Notes:
any other method like seg tree, mo's, etc, would be overkill so not listing
Solutions:
Array Division
Notes:
standard koko eats bananas style question
Solutions:
Subarray Sums I
Notes:
can use a variable sliding window or lop off method, used anti-hash salting to defend against python hashmap testcases
Solutions:
Subarray Sums II
Problem Summary:
Given a SQL table of machine activity with start/end timestamps, find the average processing time per machine rounded to 3 decimals.
Notes:
standard sum lop off problem, used anti-hashmap salting to defend against test cases
Solutions:
Towers
Notes:
binary search is easy, multiset or seg tree + coordinate compression can work but are such overkill I'm not listing as options in the tags
Solutions:
Playlist
Notes:
basic sliding window
Solutions:
Missing Coin Sum
Problem Summary:
Find the smallest amount we cannot make from various coins
Drill Type:
Implementtest ability to solve this
Solutions:
Palindrome Reorder
Solutions:
Permutations
Problem Summary:
Construct a permutation from 1...N such that no two adjacent elements have a difference of 1
Notes:
We can put all even parities next to each other, then odds. The dangerous point is only when the two parities touch. For N=4, 4 2 3 1 would fail, we should use odds first like 3 1 4 2 to get the lowest number (1) at the boundary compared to the highest starting even number.
Solutions:
Increasing Array
Problem Summary:
can increase a number in an array by cost 1, find min cost to make array mono increasing
Notes:
just greedily increase based on the previous value, can also implement with a prefix max variable
Solutions:
Repetitions
Problem Summary:
Find the longest streak of a letter
Solutions:
Missing Number
Problem Summary:
given all numbers 1 to n except one, find missing
Notes:
use sum subtract or XOR
Solutions:
Weird Algorithm
Notes:
basic simulation
Solutions:
Stick Game
Problem Summary:
We have up to 100 groups of size <= 1e6, and n <= 1e6 sticks. We can remove any group. If we remove the last stick we win. Can we win? for which stick amounts <= n?
Notes:
naive dp(sticksLeft, turn) can be optimized to be dp(sticksLeft) means this player's perspective can win. Can do bottom up too. Don't think we can use a bitset here, so it remains n * k.
Exponentiation
Problem Summary:
Compute a^b % MOD
Notes:
Binary exponentiation, can do bottom up like in the code
Drill Type:
ImplementImplement bottom up
Solutions:
Permutation Rounds
Problem Summary:
We have a permutation and each step the elements move based on their position in the permutation. What is the minimum # of steps before the array returns to normal?
Notes:
Cycle decomp + LCM of cycle sizes. However, taking the LCM of large numbers % MOD could explode. We cannot mod LCMs one at a time or we would get the wrong answer. Python passed with just one final MOD at the end of the lcm so not sure if there is some proof of a low upper bound on the LCM size. However, we could know that the LCM is just the maximum prime factors multiplied by each other for each number. So track the largest cycle size # of 2s in the prime factorization, 3s, 5s, and so on. Then multiply these together with intermediate MOD to prevent large blow-up
Solutions:
GCD Subsets
Problem Summary:
Find the # of subsets of numbers that have a GCD of x for all x <= N. N <= 1e5, A[i] <= N.
Notes:
First we want to know how many numbers are divisible by a factor, for all factors. We compute this with harmonic series in n log n. Then if we want to know how many subsets are divisible by X, we can pick or not pick any of those numbers, 2^(length of factors) - 1 (for empty subset). But that is the number of subsets divisible by X, not GCD is X. We need to exclude subsets divisible by 2x, 3x, etc. So we do a nested loop which is a second harmonic series.
Drill Type:
MindsolveReview notes
Solutions:
Fibonacci Numbers
Problem Summary:
find the nth fibonacci number, N <= 1e18
Notes:
see CSES "throwing dice" explanation for more details on matrix exponentiation
Drill Type:
Implementsolve with matrix math
Solutions:
Throwing Dice
Problem Summary:
We can roll a dice 1-6. Find how many ways (distinct orders) to get a sum of N. N <= 1e18.
Notes:
Note that f(x) = f(x-1) + f(x-2) + ... + f(x-5). We have a base case, the number of ways to roll a sum of 0 is 1. And then preceding cases f(-1) f(-2) etc all equal 0. So our initial state vector is [1, 0, 0, 0, 0, 0]T. Meaning f(0) (ways to get a sum of 0) is at the top, f(-5) is at the bottom. To progress this by 1 step, we can multiply it by this transition matrix: mat = [ [1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], ] Because this is how vector * matrix multiplication works: # [newA0] [ ? ? ? ? ? ? ] [a0] # [newA1] = [ ? ? ? ? ? ? ] [a1] # [newA2] [ ? ? ? ? ? ? ] [a2] # [newA3] [ ? ? ? ? ? ? ] [a3] # [newA4] [ ? ? ? ? ? ? ] [a4] # [newA5] [ ? ? ? ? ? ? ] [a5] Like the new f(1) term is a 1 coefficient for each previous term, added up. We need to progress f(0) n steps to compute f(n). So we multiply our vector by that matrix n times. We can use matrix exponentiation. Top down is easy, bottom up is a bit trickier. We could define our base matrix (corresponds to an exponent of 0) and iterate small to large bits. Each bit, we square our base matrix. If that bit is set, we multiply our result matrix by it. We use an identity result matrix too as the initialized value. We could do bottom up log^2n by continually finding the largest set bit and multiplying our result by M^e (using precomputed M^e). Or log n if we use bit operations to find the largest set bit.
Drill Type:
Implementimplement with matrix math
Solutions:
Factory Machines
Problem Summary:
koko eats bananas
Solutions:
Nested Ranges Check
Problem Summary:
Given a bunch of [L, R] ranges, find which ranges contain other ranges (L2 >= L, R2 <= R) and find which ranges are inside other ranges.
Notes:
Approach 2, O(n log n), TLE in python Sort ranges by (L, -R) To see if our range [L1, R1] contains a range, as we sweep right we are going to get increasing L2 which is required for containing But we need to know the smallest R2 on the right (either via suffix array, or sweep right to left), R2 has to be <= R But we need bigger ranges on the left still, consider [1, 3] and [1, 5] if sorted by (L, R), we won't see [1, 5] contains any range to its right So we want bigger ranges to be able to "see" smaller ranges on the right These issues occur only when L = L2, I thnk we could maybe sort by (L, R) and get it working still but with extra bookkeeping For the inverse question (are we contained in a range it is similar logic) APPROACH 1 Sort each range by (L, R) For each intervals [L, R], find the i...j range in our sorted array with an L_2 >= L and < R Find the smallest R out of elements in that range with a sparse table or seg tree, if R_2 < R, we contain a range Also check the edge case where R_2 = R, we can manually store the largest L for each R_2 Repeat process for second part of the question
Drill Type:
Mindsolvere-read notes
Solutions:
Distinct Values Subsequences
Problem Summary:
count the # of subsequences with all distinct values
Notes:
basic combinatorics
Solutions:
Distinct Values Subarrays
Problem Summary:
Find the total number of subarrays with all distinct values
Notes:
could do some flagrant thing like binary search with a wavelet tree but it is so obscure we won't include those even in the mentions, main way is a variable sliding window
Solutions:
Knight Moves Grid
Problem Summary:
Reconstruct the minimum number of moves to reach all cells in an NxN chess board
Solutions:
Knight's Tour
Problem Summary:
Given a starting X and Y, find a path for a valid knight tour that visits every square once
Notes:
Backtracking is slow, instead we use a heuristic, prefer to go to the next spot that has the fewest neighbors it can go to, trying to "use up" rare neighbors earlier.
Solutions:
Hamiltonian Flights
Problem Summary:
Given a graph of N <= 20 nodes, find how many paths can go from 1->N touching each node once.
Notes:
This is a hamiltonian path. We can use bitmask DP to track visited nodes. I tried push bottom up dp: for oldVisitedMask, for oldJustArrivedAtNode, for outgoing edges in that node. To AC in time, I had to prune, for instance skipping oldVisitedMasks with the Nth node already visited (can probably just iterate on half as many masks since that is the maximum bit). Also did some other pruning in the hot paths like not reaching the Nth node early. 2^n * n^2 time.
Drill Type:
Implementsolve this
Solutions:
Sereja and GCD 2
Problem Summary:
Find the # of ways to make a sequence of N positive integers <= M such that no two pairs have a GCD > 1. N <= 1e5 M <= 100.
Notes:
A naive solution is to have dp(primeFactorsUsedBitmask, countOfNumbersPlaced, numberWeAreConsideringPlacing) which is 2^25 * 100 * 100. We can observe that at most we could place ~25 numbers (all primes <= 100) so it becomes 2^25 * 25 * 100. First trick: Any prime >= M/2 could only appear once, so we don't need to track them in the bitmask. Instead they can be handled separately. This makes it 2^15 * 25 * 100. Then realize that instead of considering every number separately, we can compress them. If we consider a number with prime factors 2 and 5, we cannot consider any others with those 2 exact primes. So group numbers by their prime bitmasks, and iterate on the length of that list instead of all 100 numbers. Maybe roughly 2^15 * 25 * 50 (guessing). All of the big primes (> m/2) could be handled in a for loop outside the DP, so "we try taking 3 big primes" and then we kick off a dp call where countOfNumbersPlaced = 3. However if we don't do the big primes in a for loop outside, we can just handle that in our base case. When we run out of the mask buckets we consider placing (like the {2,5} bucket) we can see how many spots we have and choose to place big primes there. We could cache this so our base case isn't a for loop though that seemed to have slowed down the time complexity. But this drops states to 2^15 * 15 * ~50. Now we can cleanse masks. Once we take a prime bitmask option, and those primes aren't present anywhere else in the future masks, we should remove them, to collide DP states. So if we took a number that set the prime number 7 to true, but no future mask buckets contain a 7, we don't care to set that bit anymore. This led to a 0.03s solution (100x speedup). I think this logic could be used to handle the big primes too. So we let the big primes be their independent groups of size 1 in our mask buckets but they would get immediately cleansed. Might be equally fast.
Drill Type:
MindsolveRe-read full notes and code too complex to resolve
Solutions:
Sherlock and Coprime Subset
Problem Summary:
Given an array, N <= 50, A_i <= 50. What is the largest subset s.t. every element is co-prime.
Notes:
Naive is knapsack DP with a size 15 bitmask for primes <= 50. We can optimize though. I don't think we need to consider every element. For instance 8 and 2 don't need to both be considered. Group numbers by their prime factorization and consider only one from each group. Also primes >=25 can only appear once and therefore can always be taken once, so we can cap our prime bitmask to 2 3 5 7 11 13 17 19 23. Similar to "Sereja and GCD 2". We could probably also re-order elements and then cleanse bitmasks (if no future element has 2 as a prime number, we can keep that bit unset always), we did that optimization in Sereja and GCD 2.
Solutions:
Little Elephant and T-Shirts
Problem Summary:
There are up to 10 people. There are 100 unique types of shirts. The people can own different combinations of shirts in their closet. How many ways can the people wear shirts such that no two people wear the same shirt?
Notes:
Keep a mask on the people and loop over shirts, simple
Solutions:
U - Grouping
Problem Summary:
We have n <= 16 nodes and graph[node1][node2] score if they are in the same group. Divide the nodes into groups with max score.
Notes:
Submask enumeration can give us a current bitmask state of taken nodes, and pick a new group. 3^n. We also can speed up by 2x by forcing a submask to contain our smallest bit that still needs to get grouped. We can get the same partitions (that bit must be in SOME group) and skip half the states. So 3^n / 2. Think of the half states like each node being a yes/no if it is in the new group, then we fix one node to always be yes. Also use dp to cache the score of each submask which can be n * 2^n (or maybe even faster).
Solutions:
D. Traveling Graph
Problem Summary:
Find the shortest cycle (starts and end at same node) in a graph that touches every edge. N <= 15 M <= 2000.
Notes:
Note that a cycle which cleanly visits each edge once and starts and ends at the same node is an euler tour. A graph is euler tourable if all nodes have even degrees. If nodes have odd edges, we would need to walk between those nodes once to flip their paths. There can only be an even amount of odd nodes (just think about that, basic logic). So we collect odd nodes and need to pair them together via the shortest path between them, as an extra walk, to make it "even" nodes. We can get the shortest distance between any 2 nodes with a variety of methods, like floyd warshall. Any path starting at X and ending at Y would only flip the parities of the end points. Use DP bitmask on the odd nodes, n * 2^n complexity (least set bit must get paired with something, like "Looking for order" problem on codeforces. Watch for weird traps like a graph of just nodes with no edges.
Solutions:
D. Tree Jumps
Notes:
A naive DP is to loop through all nodes except children for a given node, which should explode in complexity. Instead, we cache the result for the entire layer in a separate DP, and then call layer - all children for a given node, which amortizes.
Solutions:
E. New Year's Gifts
Notes:
One way to solve it: First pay all the y coins to everyone. Sort friends by lowest box beauty first, and our gifts. For each gift, find the rightmost friend we could make happy with that gift. This defines a contiguous 0...R range we can make happy with the gift. Find the highest coin amount in there, and use the gift for that friend. To find the highest coin amount there and update it, use a segment tree. I think we could also do a similar thing but we maintain a multiset of friends that we could make happy with our gift. We pop the largest coin value from it.
Solutions:
840. Magic Squares In Grid
Notes:
manual brute force, light pruning options
Solutions:
G - Longest Path
Problem Summary:
Find the longest path in a DAG
Notes:
Could also do this: 2) DFS postorder topo sort Run DFS, and when you finish exploring a node, push it into a list. At the end, reverse that list = topo order. Why it works: in a DAG, when you finish u, all nodes reachable from u have been finished, so u should come before them in topo order (after reversing).
Solutions:
Game Routes
Notes:
looping on edges amortizes
Solutions:
D. Even String
Problem Summary:
We are given n letters and need to partition them into groups of size n//2 and n-(n//2) with order mattering. How many ways can we do this?
Notes:
We can partition the groups with 0/1 knapsack as there are only 26 pieces. But once we partition them, say [a, a, b, b, b, b, f] [c, c, c, e, e, e, g] how do we know how many ways with order mattering can be formed? It would depend on the specific partition chosen. Like on the left side would be 2! * 4! * 1! options. We can find this out for one partition but not all possible partitions. Well observe that for a given partition, the ways to create the left is (a+b+f)! / a! * b! * f! [any element not in the right group]. The right is (c+e+g)! / c! * e! * g! [any element not in the left group]. Then the total ways is those two numerators times denominators. It doesn't matter what the chosen elements were, we get odd! * even! / each letter !. See editorial: https://codeforces.com/blog/entry/141425
Solutions:
B. New Year Cake
Notes:
could simulate or binary search on the most number of rows for each color type, I think there is even an O(1) math
Solutions:
C. Production of Snowmen
Notes:
Maybe there is a faster way, I did n^2, can use a queue or two pointers. Pick up to n positions for the first row. Pick up to n positions for the second row depending what works. Last row gets forced placements.
Solutions:
D. Christmas Tree Decoration
Solutions:
D. Fibonacci Paths
Notes:
A naive dp is dp(edge) and we recurse to all neighbor nodes with the right target size. Even if we determine ahead of time "only visit these neighbors with this size" it doesn't amortize, imagine n/2 edges in a spoke graph pointing to a center with outgoing edges from that center all going to a future valid node. We would get n/2 starting and n/2 ending nodes which is n^2. Instead, dp(node, needVal) is better. It can take on only E states (1 per edge) but it compresses things better. Because when we are at the center spoke node in the graph we will cache a result and not revisit things too many times.
Solutions:
C. Needle in a Haystack
Notes:
Take the extra letters from the bigger string and sort them. Those can go wherever. Now run two pointers and greedily take the smallest letter from that and from our target string. If a tie, we should always take from target string in case there is a smaller letter after (the sorted section can only go up lexicographically)
Solutions:
B. Optimal Shifts
Notes:
When we shit we spend 1, so shift until all are covered. Just find the longest gap of 0s we need to cross those all.
Solutions:
A. Operations with Inversions
Notes:
A number can always be removed if there is a bigger number on the left. Don't remove a number until we have removed all smaller numbers. So just use prefix.
Solutions:
B. XOR Array
Notes:
I randomly generated numbers but if we ever would match a previous prefix XOR it means we cannot use this number. Even generating numbers up to 10^9 there is an >99% chance of a prefix collision, I think. So I had to loop and regenerate. Also use a 1e8 bound not 1e9 otherwise when we are forced to place the single number at R that creates an XOR for L...R of 0, that forced number might be too big.
Solutions:
A. Little Fairy's Painting
Notes:
basic greedy
Solutions:
B. Wishing Cards
Notes:
Hard question, read `prefix DP.py` and the actual notes in the github problem URL for learnings. There is apparently another k^3 DP (on values instead of the people?) that is n + k^3 by the other. It can be solved with CHT too and li chao tree: https://codeforces.com/blog/entry/149003?#comment-1330854
Solutions:
C. First or Second
Problem Summary:
We have N <= 2e5 children with abs(niceness-es) <= 1e9. X initially is 0. We will choose the first or second child in the line, remove them. If the first we add their niceness to X, otherwise subtract. Find the max X we can get.
Notes:
One child will be left in line, fix this child. All children after them must be subtracted, all before must be removed. Subtracted suffixes are easy. The fully evicted prefix we can do: -We must take the 0th child to evict the prefix up to our fixed position for other children in the prefix: -If a child is negative, we should take them when they are in the second position, if they are positive, move it to the front position first.
Solutions:
B. Impost or Sus
Problem Summary:
We have a string s <= 2e5 of 's' and 'u'. It is sus if 's' appears at least twice and for every u, the nearest two s are the same distance from it.
Notes:
A 'u' cannot be adjacent to another 'u', or we will have differing lengths for some 'u' in that chain. Also a 'u' cannot be on the edge. Scan left to right, make the edges 's'. If we encounter a 'u', if the previous letter was a 'u', we must change it. There is some other greedy logic I intuited but didn't make it airtight.
Solutions:
A. Yes or Yes
Problem Summary:
We have a string of Y and N, we can merge two adjacent characters using the OR operation, but never want to merge Y OR Y. Can we reduce the string to size 1?
Notes:
Invariant: A merge cannot decrease the number of Ys. If we have more than 1, we fail. If we have <= 1, we can merge any two pairs.
Solutions:
RAONE - Ra-One Numbers
Problem Summary:
A number is RA-ONE if the sum of even position digits has a difference of 1 from the sum of odd position digits. Find the # of RA-ONE numbers in a range L...R <= 1e18.
Notes:
This problem requires getting the difference of sums between even and odd indices, indexed from the right. We can easily do this without tracking an extra sequenceLength or anything. If we are at index i, and the upper bound is length n, we can just infer the position # 0 1 2 3 4 # ^ placing here must be odd index (from the right, 1 indexed) If needed the position from the left, I think we can just track it with a hasStarted boolean (which itself does not need to be part of the cache, I think it can get optimized out from the memory allocation like the tight flags can be), and a parity flag, as soon as we place our first digit that starts the sequence we can keep the parity flag updated. Needed C++ to pass the 0.1s limit
Solutions:
CPCRC1C - Sum of Digits
Problem Summary:
Find the sum of all digits for all numbers between L and R.
Notes:
When we add a digit, to know how much it contributes we also need to know how many numbers can be formed after adding this digit. So our digit DP is dp(i, tight) and returns (totalSum, numberOfDoableNumbers).
Drill Type:
Implementimplement this
Solutions:
F. Jee, You See?
Problem Summary:
We are given n, L, R, Z. n <= 1000. L <= R <= 1e18. Z <= 1e18. Find how many sequences containing non-negative integers, of length n, exist, with L <= sum <= R and the bitwise XOR is Z.
Notes:
An easier subtask is to ignore the XOR. First find how many ways to construct N numbers with sum <= R. Then we will do F(R) - F(L-1). Going number by number is hard because there are so many options for each of the N spots. We will go bit by bit. When we consider the largest bit (say 32) we can only set that bit in so many spots, bounded by R. We can also figure out n choose k ways to place those bits, for a given amount of placements we choose to make. We will try placing 0 bits, 1 bit, 2 bits, all the way up to the max of this bit type we are allowed to place. Using combinatorics to help compute # of ways. But how do we know how many bits we can place? Say R = 16. The moment we place a single 2^4 bit we need to remember this when we try placing 2^3 bits. We cannot keep a `budget` parameter in our DP because it is too many states. Instead, our `budget` parameter will track how many of the next bit we can place coming from the previous states. Initially this is 0 since there are no previous states. We are going to start at a really big bit. If R has that bit set our budget goes up by 1. Say we can place up to 5 bits, try all combos from 0-5 bits. If we place 3, our budget left is 2. But when we drop a bit, the budget left will double because those bits are half as big (new budget 4). Note that at any point we only ever need 2*N budget. Why? Say we place every single bit set in our current layer, spending N budget. All of those bits are bigger than everything else remaining, like [1000, 1000, 1000, 1000] is bigger than [0111, 0111, 0111, 0111] so we don't need to worry about a budget bigger than 2*N. This feels a bit not airtight but just think about it some more. We start with a budget above of 0. As soon as we hit the biggest bit in R we can only place 1 of those numbers. If we don't, we can only place 2 of the next number and no smaller numbers. Any remaining smaller bits we want to place will get picked up by when we increment the budget by 1 due to a bit being set in R. Now to handle the XOR, if that bit is set in Z we can only place odd amounts of bits, otherwise even.
Drill Type:
MindsolveI guess just re-read notes lol
Solutions:
E - Digit Sum Divisible
Problem Summary:
Find how many numbers <= 1e14 are divisible by the sum of their digits.
Notes:
A reasonable upper bound for the maximum digit sum is 9 * 15, put a 9 in every spot. But when we run the digit DP, both the remainder and digit sum are changing, so it is hard to track both. Instead, loop over each possible digit sum separately. Then do dp(i, remainder, currentSum). We can do this trick to increment remainder as we slide (or just precompute d * pow10): (remSoFar * 10 + digit) % s
Drill Type:
Implementimplement to practice the sliding remainder thing
Solutions:
C. Classy Numbers
Problem Summary:
A number is classy if it has at most 3 non-zero digits, find the # of classy numbers in L...R
Notes:
I avoided the 2 x 2 extra dimensions by not caching highTight and lowTight. Guessing combinatorics can be used.
Solutions:
G. Maximum Product
Problem Summary:
Find the number from the range [a, b] which has the maximum product of the digits. a, b <= 1e18
Notes:
For digit dp we need dp(i, tightHigh, tightLow, isStarted) to get the maximum digit product. We need both low and high tight because we cannot diff results like dp(b) - dp(a - 1) since we are looking to get a maximum product, not a count of #s in a range. So if the maximum product we can form with numbers <= b, is 240, we cannot say that this is formed with numbers >= a. Our options for the number are: -neither tight -one is not tight, the other is tight -both are tight (shared prefix so far) In the cases where either is tight, we have deterministically arrived to this state from one exact sequence of nodes, we could not arrive here from more than one place, and no caching is needed since we can only enter this node once. I made the cache only i * isStarted size (meaning n * 2). We didn't need tightHigh or tightLow in the cache because there are stick patterns. Imagine DP charts are like a DAG, every node can recurse to multiple next nodes, and nodes can have multiple incoming edges from previous states. However whenever we are tight, it implies we came from one exact predecessor, so there is no point to cache it. See the code. The cache stores the maximum product that can be gotten from those DP params. I still allocated an n * 2 * 2 * 2 nxtDigit array which tells us the optimal next digit to pick in the reconstruction, but this actually isn't needed. We can just execute our dp then again trace back through every digit and determine the best one live, and transition to the next state. We can also allocate a nxtState n * 2 * 2 * 2 array (I did not) but again it isn't needed since we could determine it on the fly, like I did. Also if we want to track the nxtDigit array it cannot just be nxtDigit[i] or nxtDigit[i][started], it depends exactly on the specific node we are at in the DP DAG, even if we aren't caching things due to something being tight, we are at a unique node and need to know the selected digit to reach the next node. Note that I don't think we can directly construct the answer inside the DP function, we need to first call the DP function and then construct after. I need to think about this more. Not sure if doing bottom up changes this too. There is also a greedy to this solution I believe hence an easier rating.
Solutions:
12747 - Back to Edit Distance
Problem Summary:
Find the LCS of 2 permutations from 1...n. N <= 1e5.
Notes:
Imagine we transform A -> B with some operations There were some elements (possibly none) in A that we never deleted They appear as a subsequence in B too Everything else got deleted and therefore re-inserted So the optimal answer requires finding the LCS and then the remaining elements each use 2 operations How to find LCS? [1, 3, 5, 4, 2] [1, 5, 4, 3, 2] remap the first array to be the indices they occur in the second array [0, 3, 1, 2, 4] now an increasing subsequence in the indices implies we saw those from left to right in array B we also saw them from left to right in array A because we read it from left to right this is a common subsequence then as it appears left to right in both A and B to find the longest common one, then we just find the LIS on the indices array
Drill Type:
Implementimplement this
Solutions:
F. PolandBall and Gifts
Notes:
We decompose the groups into cycles. If k balls forget their gifts, and we can form a subset sum of exactly k, that is the minimum. Otherwise, we take a bunch of full group cycles, and one non full group. So if our cycles are size [2, 5, 7, 30] and k= 20 we can fully lose the 2+5+7 balls and 6 balls in the 30 group also forget. Any time X balls in a group forget, and we want to minimize lost gifts, place them adjacent, and we lose 1 extra gift. So the minimum is either k or k+1 depending on if the subset sum k is feasible. Some optimizations (not sure how many will be needed): -rootN unique sizes observation to get fewer components to knapsack on -Bundle splitting technique, but I don't think the time complexity changes when S is <= 1e5 anyway, worst case the cycles are size 1, 2, 3, ..., root N where bundle splitting does not reduce anything. -Bitset for feasibility They might all be needed due to tight time limit. Used union find to find component sizes. For the max possible gifts lost, even sized components can lose their full gifts with just half the members forgetting. Odd sized components we can basically use a greedy. Monotonic deque could maybe work too but I think it is no different complexity from bundle splitting since S is capped.
Solutions:
Tree Upshot
Notes:
WLOG, the root node can be either color, adding 1 to the cost. Each child node should be an inverse color by force, because their costs would be 0, and also provide freedom for either color for the grandchildren. This means even depths (0-indexed) we get to pick colors and odd depths are forced to flip. For each node at an even depth we can pick its color, and all its children get flipped. This means our subset sum sizes are (# children - 1) for each even depth node. We need to find the largest subset sum we can form with these components (just the sum) and also the sum closest to 0. Instead of the one closest to 0 I found the one closest to half the total sum with a bitset. There are at most rootN unique component sizes and we are doing feasibility checks so we can use both bundle splitting and bitsets but not sure how necessary either is.
Solutions:
E. Lucky Country
Notes:
Observe there are at most rootN unique component sizes. This means we can knapsack on root N items + how many times they occur. Then we binary bundle split on the # of island sizes we have for each island type, making the number of bundles basically log(something) * rootN. But actually I think the log factor doesn't exist. It should get amortized globally. Say we have worst case rootN unique sizes then each unique size would only have like 2 bundles. Not fully formalized but seems right. Also note there are at most 2 root N unique sizes if all numbers are distinct and sum to N. Just imagine filling up a right triangle, first a column of height 1, on the right a column of height 2, and so on up to root N. That should fill half of an N x N square. I don't think the bundles is necessary also, see my "Subset sums DP" guide on github, I think the bundling doesn't do anything. Because if we have rootN unique sizes each occurring once, the # of components does not change with bundling, but I couldn't get AC without bundling (even on C++). For each of those ~1000(?) bundles we can take or not take it like 0-1 knapsack style. We need to know the min number of islands to be merged for all island sizes from 1 to N. So we maintain dp[islandSize] = min # of merges needed. So n * rootN. Initialize base case only to dp[0] = 0, not dp[somePremadeIslandSizeWeHave] = 0. Because the dp array initially represents answers before any items are processed. Otherwise we would accidentally double count things, like if we initialized dp[2] = 0 then we considered our first island of 2 nodes we might form dp[4] but that's invalid, we used the same island of 2 nodes twice. I believe we could use some sort of monotonic deque DP here too but I think it might not improve complexity since S is bounded by 1e5 and so bundle splitting actually doesn't improve complexity.
Solutions:
B. Little Pony and Harmony Chest
Notes:
A lot of lessons in this: Number theory portion is no two numbers share a factor if they don't share a prime factor so we decompose into primes and track taken prime bitmasks (~17 primes <= 60). Top down unoptimized python TLEd. Bottom up also TLEd but is solveable (see yawn-seans: https://codeforces.com/contest/453/submission/222623781) His optimizations precomputed valid choices per-mask so it wasn't repeated inside the hot path I had. He also didn't need a prevChoice array in the dp reconstruction, since all DP transitions are a +- transition he just subtracted a mask to get to the previous state. He also did some pruning thing that required sorting. Top down DP is pull. It feels like we are picking the "nextState" choices but it is actually a prevState since it is recursive. Note that this reconstruction required choices with an extra `n` parameter as we have to iterate back on the `n` axis: prevMask = [[-1] * (fmask + 1) for _ in range(n)] prevChoice = [[-1] * (fmask + 1) for _ in range(n)] Yawn sean also had a second entirely different solution that was faster, seems to be some number theory coprime thing: https://codeforces.com/contest/453/submission/222618899 That is harder than the `3` rating I gave for number theory (that was the rating I gave for the main DP solution)
Solutions:
A. Gym Plates
Notes:
A few lessons about N-ary masks here. 1/ Why is it that all binary masks uniquely map to base 10 integers? Because 2^x is > than the sum of all 2^(y) where y < x. If we binary masks somehow had the same base10 integer: We claim there is at least one bit they differ by. Find that highest bit. The other mask cannot make up that 2^x sum with all remaining bits. 2/ We have a mask which is a number in base 10, but we are treating it as some encoded base 3 data. So 100 (base 10) might "mean" 10201 in our base 3 info. 3/ To extract the value of one of those encoded base 3 digits, like the 2, we can floor divide our base10 number by 3^i and take the remainder. Remember a floor division on 100 in base 10 is doing a right bit shift on the SAME number in base 3.
Solutions:
C. Looking for Order
Notes:
A naive solution is have a placedItemsMask and enumerate n^2 combos to try placing them for O(n^2 * 2^n). Instead we can consider a mask and know the least set bit can either go alone or be paired with one of n other options. This is O(n * 2^n). We can do top-down pull dp by looking at a mask and saying that mask must have come from some submask where the least set bit was just set. We can also do pull dp bottom up. I did push dp bottom up though which feels more intuitive. For a given mask we can push a possible route to the future state. For dp reconstruction we cannot update nextDpState[state] -> nextState every time we improve dp[nextState] from our current state, that is the wrong order. That means the best incoming edge into nextState is this edge, NOT the best outgoing edge from our current state. Instead we store a prevState and also prevBagsPlacedChoice (optional, but may be easier to help with reconstruction to avoid computing it twice), then reconstruct backwards. To get python to pass in time I had to skip masks I was enumerating on if dp[mask] = INF (no point pushing here). This can occur because not every mask is reachable when following the "only set least unset bit" rule.
Solutions:
E1. Prime Gaming (Easy Version)
Notes:
We cannot represent the current numbers taken so far with a bitmask, because we don't know how to capture the initial configuration of the board. We want to enumerate each board and also solve those boards quickly (if Alice can force a 2 at the end). Our bitmask will capture both the board-state and implcitly the initial configuration. We excise a bit from a spot when we remove it. Track the number of piles in the dp too since just the mask is not enough info, like 001 and 01 are different masks in this case. We also track whose turn it is which is a derived value. We can therefore remove that parameter, but we cannot remove the concept of turns like we can for other game theory problems: You can “do away with turns” only in games where the move rule doesn’t depend on whose turn it is, i.e. both players have the same move set and the only difference is objective (maximize vs minimize). Then you can write a single recurrence. GPT says: You can “do away with turns” only in games where the move rule doesn’t depend on whose turn it is, i.e. both players have the same move set and the only difference is objective (maximize vs minimize). Then you can write a single recurrence like: V(s) = max over a in Moves(s) of V(next(s, a)) if the game is actually “current player always maximizes their own payoff” and the payoff is from the current player’s perspective, so it flips each turn automatically. But your game’s payoff is not “whoever moves last wins” or “current player’s payoff”. It’s a fixed payoff: Outcome = value of final pile x. Alice always wants max x, Bob always wants min x. That payoff is anchored to Alice’s preference, not “current player”. So if you write “current player maximizes”, Bob would be maximizing too — which is the wrong game. When can you eliminate the turn variable? Two common cases: Zero-sum with player-relative payoff e.g. winner/loser games where value is +1 for current player win, −1 for loss. Then you can store V(s) = advantage for player to move. Recurrence becomes: V(s) = max over a of ( −V(next(s, a)) ) No explicit “whose turn” needed because the sign flip encodes it. If turn is derivable from the state like here: turn parity is determined by numPiles (or moves made). Then you don’t store turn, you compute it from parity (which we already did). But the concept of alternating max/min still exists. ------------------------- Example 1: Take-away game with “current player wins” payoff (sign-flip trick) Game: There are N stones. On your turn, remove 1 or 2 stones. If you take the last stone, you win. Define: V(n) = +1 if the player to move from state n will win with perfect play, else −1. Then you don’t need a turn variable because “player to move” is built into the definition. Recurrence: If you remove 1 stone, the opponent faces n−1, whose value is V(n−1) for them. For you, that outcome is −V(n−1). If you remove 2 stones, the opponent faces n−2, whose value is V(n−2) for them. For you, that outcome is −V(n−2). So: V(0) = −1 (no moves: player to move loses) V(n) = max( −V(n−1), −V(n−2) ) for n ≥ 1 No explicit turn variable is needed because the sign flip automatically encodes whose turn it is. Example 2: Turn is derivable from the state (parity) Game: Players alternate turns, but the number of moves made is determined by the state itself. In your pile-removal game: Start with n piles. Each move removes exactly one pile. At a state with numPiles remaining, exactly (n − numPiles) moves have occurred so far. Therefore: If (n − numPiles) is even, it is Alice’s turn. If (n − numPiles) is odd, it is Bob’s turn. So you do not store a “turn” variable in the DP state. You only store (numPiles, mask) and decide whether to take max or min based on parity. The alternating max/min logic still exists, but the explicit turn variable is eliminated.
Solutions:
C. Square Subsets
Problem Summary:
We have N <= 1e5 numbers <= 1e7. Find the # of ways to pick a subset such that the product is equal to the square of some number.
Notes:
A perfect square is one whose prime factors all have even exponents, since it implies we can multiple a number with X exponents by itself, like 2^x * 2^x = 2^(2*x) and 2*x is always even. We maintain a bitset for the current odd frequency prime factors (only ~19 up to a[i] <= 70). We enumerate each unique type of number and see how many ways we can pick an odd amount from this number type and how many to pick an even number type (basic math trick, they're the same amount). I used push-dp on bottom up but also wrote a top down that MLEs.
Solutions:
E. Fish
Problem Summary:
We have N <= 1e18 fish. Every day a pair meets and all pairs have the same chance of meeting. there is an i,j map which tells us the chance of i eating j and vice versa. Find the chance for each fish it is the last survivor.
Notes:
Naive dp solution is dp(currentDeadMask) and it stores the probabilities of size n to end on that fish last. We enumerate n^2 pairs inside for a total of n^3 * 2^n which is too slow. Instead make dp[currentDeadMask] be the chance we ever reach this state. We can use push-dp (most natural). For a given mask, we choose 2 living fish and make them battle, then push into the next state.
Drill Type:
Implementre-mindsolve and implement
Solutions:
B. Modulo Sum
Problem Summary:
We have N <= 1e6 numbers <= 1e9 and M <= 1e3. Can we pick a subsequence that is divisible by M?
Notes:
O(n + m^2) solution: If n>m, we will prove we can always find it for a subarray (which is also a subsequence). Since our n prefixes must have at least one repeating modulo. This means those two prefixes with a repeat modulo form a subarray divisible by m so the answer is yes. If n<m, we can solve with knapsack dp O(n * m / W) solution: I solved it with a bitset which is n * m / W complexity. Track doable remainders of subsequences with a bitset. Use a clearance mask to keep the bitset small.
Drill Type:
Mindsolvere-read notes, both cool ideas
Solutions:
E - Knapsack
Problem Summary:
We have items with weights 1 to 8, and up to 1e16 copies of each. We want the maximum subset weight that is still <= W <= 1e18. Find this max weight.
Notes:
we need to know the most blocks we can take for certain remainders. Claim is that the max remainder we need to consider is 8*840 - 1. Why not a larger remainder? Any sum >= 8*840 necessarily has a block of 840 fully formable by one number type. We could subtract that full block and have dp[remainder - 840] + 1 already capture that case. What is the lower bound on the remainders we need to consider? Not sure but I tried 839 and it got WA. Seems hard to prove a lower bound.
Drill Type:
Mindsolvere-read notes
Solutions:
E - Colorful Subsequence
Problem Summary:
We have N <= 2e5 balls with C <= N colors and V <= 1e9 values. We want to remove K <= 500 balls so no two adjacent balls have the same color, and we want to maximize the remaining value. Return the max value we can have or -1 if not doable.
Notes:
A naive solution is dp(index, currentBallsRemoved, lastBallColor) but this is too many states. We need to drop lastBallColor. How? We store 2 values in our dp. DP(index, currentBallsRemoved) -> [(highestScore, lastBallColor), (highestScoreWithDifferentBallColor, differentBallColor)]. Now no matter what the new ball color is, we know the continued path we can take.
Drill Type:
Implementprobably re-read notes and recode too
Solutions:
D. Yet Another Minimization Problem
Problem Summary:
We have two arrays of size N <= 100. In an operation we can swap a_i and b_i. The cost of a is (a_i + a_j)^2 for all i,j. Same with b. Minimize the cost of both arrays.
Notes:
For a given pair (x+y)^2 it expands to x^2 + y^2 + 2xy. So the x^2 and y^2 both occur regardless of which array they are in. We need to minimize sum of 2xy for all pairs for both arrays. Maintain dp(index, prevASum, prevBSum) where prevBSum is a derived value. Try knapsack DP. A bitset could be used with a different DP formulation (I think regarding minimizing differences between the two arrays?) but I didn't learn it.
Drill Type:
Mindsolvere read notes
Solutions:
Moving Robots
Problem Summary:
We have an 8x8 chess grid filled with robots. Each robot moves K <= 100 squares randomly. Find the expected # of empty squares.
Notes:
dp(startR, startC, endR, endC, stepsLeft) tells us the chance we avoid ending at (endR, endC) with the starting coordinates. Then we use linearity of expectation. I think we can use matrix exponentiation to go from k to logK in the time complexity. The only “asymptotically faster” idea If k were huge, you could use matrix exponentiation. • Build a 64 by 64 transition matrix M, where M[u][v] is the probability of moving from square u to square v in one step. • After k steps, the probabilities are given by M raised to the k-th power. The probability that a robot starting at s ends at t is M^k[s][t]. • Compute M^k using fast exponentiation in O(64^3 * log k) time.
Drill Type:
Mindsolvere mind solve
Solutions:
Counting Towers
Problem Summary:
We want to find how many ways to build a 2xN tower with N <= 1e6 using any sized AxB blocks.
Notes:
We can use matrix exponentiation to get log(N) per query. I also just did dp(i, parity) which tells us which of the current 2 are filled. We can extend, close, restart, etc
Drill Type:
Mindsolvequick re-read of code / notes
Solutions:
Apple Division
Problem Summary:
We have N <= 20 apples with weights <= 1e9. Find the min difference in weight of 2 groups.
Notes:
Can generate all 2^n subset sums in 2^n time and just check those. Can split into halved groups and generate 2 * 2^(n/2) sum groups. We will analyze subsets from the left half and combine them with subsets from the right half. We cannot do a nested loop for leftSum in ... for rightSum in ... since that is 2^(n/2) * 2^(n/2) which is just 2^n. Instead for a given sum from the left, we want to know the best sum frop the right to put into the same group A. We can use binary search or two pointers on each half. So leftHalfSums we set i=0 and rightHalfSums we set j =n-1 and run a sorted two pointers.
Drill Type:
Mindsolvere-read notes some cool stuff
Solutions:
Counting Tilings
Problem Summary:
Your task is to count the number of ways you can fill an n * m grid with 1x2 and 2x1 tiles.
Notes:
We need to, for a given mask, see the next transitions we can arrive to. Our future mask # of ways will be the sum of previous cases it came from. I used a DFS to generate the next transitions. But we could use submask enumeration, which is 3^n, but the dfs is ~2.4^n I think because there's still some invalid cases that we avoid with the dfs. I used ndp because we are updating masks in a seemingly random order so this felt safer. ndp needs to reset to [0, 0, ...] not just duplicate the dp.
Solutions:
Book Shop II
Problem Summary:
We have N <= 100 different books. The shop sells C_i <= 1000 copies of each. Each book also has P_i <= 1000 pages and H_i <= 1000 price. We spend at most X <= 1e5. Max # of pages we can get?
Notes:
# Decompose all 100 book types into log(copies) bundles, worst case is n * log(copies) bundles # Run 0/1 knapsack on those enumerating the dp[cost] -> max pages, for each item, which is n * cost # Final time complexity: O(n * log(copies) * maxBudget) We can drop the log(copies) factor by using a monotonic queue. Both solutions in github.
Drill Type:
Mindsolvere-read code, I guess bundle splitting and the mono deque I did
Solutions:
Elevator Rides
Problem Summary:
We have N <= 20 people who want to get to the top of a building with an elevator. We know their weights and the elevator max weight all <= 1e9. What is the min # of trips?
Notes:
Consider a mask where 1 represents we have put this person in an elevator (either already sent to the top, or in the current elevator we are loading up). We want to know given a mask, the min (elevatorsSentToTop, currentElevatorWeight). In top down, we can look at a mask dp(mask) and say "this state must have come from a previous state with 1 fewer bit". So we enumerate all those n submasks and check their previous (elevatorsUsed, currentWeight) and see if we can fit this new bit in to that or if we need a new elevator. This is pull DP since top down cannot push, unlike bottom up, as it requires updating things above the recursive tree and creating side effects. In bottom up, we can do push or pull. We can enumerate the masks in order from 1 to fullMask because each mask requires a submask numerically smaller than it (1 fewer bit set) so that order is safe. We could also enumerate masks first by # of bits set then generate all masks with that many bits set via something like gosper's hack See solution for both push and pull bottom up. Also note in our solution we used (0, 0) as the base case and added 1 to the answer. We can always add 1 to the answer (instead of checking if the last un-closed weight is 0 or not) because that can never happen. The last item we pack will always make sure our last un-closed knapsack has weight in it. We could also make the base case (1, 0) instead.
Drill Type:
Mindsolvere-read notes
Solutions:
Meet in the Middle
Problem Summary:
We have N <= 40 numbers <= 1e9, how many ways can we choose a subset of sum X <= 1e9?
Notes:
Split the array in halves and generate subset sums for each half. If we are smart we can generate a subset sum in 2^(n/2) instead of n*2^(n/2) by using sum doubling (see solution). We can use dictionaries two coalesce the sums from each half, or sort and use two pointers. Bitmask DP can also generate a subset sum half in 2^(n/2): def subset_sums_lowbit(a): m = len(a) sums = [0] * (1 << m) for mask in range(1, 1 << m): lsb = mask & -mask # value of lowest set bit, e.g. 8 b = (lsb.bit_length() - 1) # index of that bit sums[mask] = sums[mask ^ lsb] + a[b] return sums
Drill Type:
Mindsolvewe should read the notes and see the clean implementations of this / how to generate subset sums quickly
Solutions:
School Excursion
Problem Summary:
We have N <= 1e5 kids who can go to one of two attractions. M <= 1e5 pairs want to attend the same attraction. For each i <= n, print if we can have exactly i kids go to the first attraction.
Notes:
Get component sizes for everything, assign them to one of two places. We can use a bitset. So I think that is worst N unique components and a bitset of size N so N^2 / 64. Now note for each unique size (up to rootN unique sizes) we could bundle split them too. That gives some upper bound of rootN * logN components so we get rootN * logN * N / 64. There is some n root n approach with monodeque dp I didn't look into it Supposedly NTT can be used but I don't understand it. Bundle splitting could be used but I don't think it improves complexity since we have at most root N unique sizes, also wasn't needed to AC.
Drill Type:
Mindsolvere-read notes
Solutions:
3780. Maximum Sum of Three Numbers Divisible by Three
Problem Summary:
Given an array of numbers, pick 3 numbers with a sum divisible by 3. Find the max sum. N <= 1e5.
Notes:
We can do basic combinatorics like pick three numbers all with remainder 2. I think this complexity scales nicely with the remainder and pick count, it's like n + f(rem, pick) instead of n * rem * pick. Can use bucket sort for each remainder bucket. Knapsack dp is the multiplied time complexity. We can do it with ndp or without in a few different ways.
Solutions:
Maximum Subarray Sum II
Problem Summary:
Given an array of n integers, your task is to find the maximum sum of values in a contiguous subarray with length between a and b. a <= b <= n <= 1e5.
Notes:
We basically do a fixed sliding window, we loop right accumulating our prefix sum, and we cut from the left end when we drop out the left. We need the minimum prefix that we can cut using the monodeque, or something like that
Drill Type:
Implementchallenge to implement the mono deque / prefix cutting logic
Solutions:
Y - Grid 2
Problem Summary:
We have a grid of size NxM N,M <= 1e5. With Z <= 3000 filled squared. Find the # of paths from 1,1 to the bottom right, moving only right or down, we cannot get stopped by a square.
Notes:
# of ways without obstacles is combinatorics sort stones by (r, c) then enumerate on stones, for each stone, we have a dp[stone] that tells us the # of paths that first get blocked by this stone for each stone, iterate over all previous stones and subtract the # of paths that would’ve gotten blocked by that (multiples by the # of paths between the two stones) return dp[-1] (we append a faking ending stone at the end) n^2 + combinatorics
Drill Type:
Mindsolvere-read solution, and code for # of paths without being blocked
Solutions:
F - #(subset sum = K) with Add and Erase
Problem Summary:
We have Q <= 5000 operations. We either add a ball with X on it to a box, or remove it. After each operation, find the # of subset sums equal to K. K <= 5000 and X <= 5000.
Notes:
dp[x] is the number of ways to make X as we add elements, we scan right to left to avoid a new_dp array but as we remove, we actually scan left to right, for instance if we have two 5 balls, we have 2 ways to make 5, and one way to make 10 if we remove a 5, we don’t subtract 2 ways from 10, since there aren’t actually 2 ways to make 5 anymore, so we need to go left to right
Drill Type:
Implementimplement this and re-read notes
Solutions:
F - LIS on Tree
Problem Summary:
We have a tree with N <= 2e5 nodes, and values <= 1e9. For every node in the tree, find the shortest path from root to it, and the length of the LIS on it
Notes:
using the n log n LIs with binary search, we dfs on nodes and add them, recurse on children, then rollback, I used my rollbackLis template
Drill Type:
Implementimplement rollback lis DRILL 1: 4/24/26 1/ history stores (index, oldValue) or (-1, 0) indicating a push_back on the dp array 2/ we need a strictly increasing subsequence, for the binary search LIS there are two framings that do the same thing: 1: search for the rightmost number we are strictly bigger than, update one index to the right (or push back if none) 2: find the leftmost index value we are <= to (kind of confusing) https://atcoder.jp/contests/abc165/submissions/75211753
Solutions:
F - |LIS| = 3
Problem Summary:
We want to form sequences of length N <= 1000 with all values from 1 to M, M <= 10, and LIS is exactly 3. How many are there?
Notes:
store the minimum number ending for a sequence of length 1, 2, and 3 and do digit DP the top down (i, min1, min2, min3) would just be a bottom up of min1*min2*min3 and we iterate on i…
Solutions:
L - Deque
Problem Summary:
We have N <= 3000 numbers <= 1e9. We take turns removing numbers from the left or right. Two players. One is maximizing X-Y and one is minimizing. Max score?
Notes:
dp[l][r] is the maximize difference a player can get (from their perspective) we don’t need a state tracking whose turn it is (we could also derive whose turn it is and use extra logic, but we don’t need that either) we either take the left or the right and subtract the max difference the opponent can get we can also make the dp just maximize the score and be turn-independent but I think we need prefix sum dp for this also the outer loop iterates on length, inner loop on the left boundary we can space optimize to 1d but it is more complicated
Solutions:
D - Knapsack 1
Problem Summary:
We have N <= 100 items weights weights <= 1e5 and values <= 1e9. We want to select items with total weight <= W <= 1e5, max value?
Notes:
I did bottom up where rows are indices and column is size 100 bag weights dp[i][w] represents the best value we can get using the first i items with exactly a bag weight of w, then we return max(dp[-1])
Solutions:
K - Stones
Problem Summary:
We have N <= 100 numbers all <= K <= 1e5. Every turn one of two players can remove one of those numbers of stones (we start with K). Find who can win. You lose if you cannot play.
Notes:
top down I did C++ dp(stonesLeft, playerTurn) and inside we loop over removing all stones, I don't think we need to track the player turn though, just if this current player can win bottom up without that 2x parameter I did dp[x] tells us if the player going now can force a win with x stones left, then we loop on each x and then each move and if the previous dp couldn’t win, we can
Solutions:
E - Knapsack 2
Problem Summary:
We have N <= 100 items with weights <= 1e9 and values <= 1e3. Find the max value we can get with a total weight <= W which is <= 1e9.
Notes:
dp[madeValue] tells us the minimum weight we can make, outer loop iterates on elements, inner loop I did backwards and used push dp to re-use the same dp array. So n*value time
Solutions:
I - Coins
Problem Summary:
We have N <= 2999 coins, N is odd. Each coin has different heads/tails probabilities. Find the odds of having more heads than tails.
Notes:
I did dp[i][heads] is the probability to get exactly heads using coins 0…i loop on i, then heads can optimize to 1d space by just preserving the previous layer
Drill Type:
Mindsolvemindsolve, read code
Solutions:
Q - Flowers
Problem Summary:
We have N <= 2e5 flowers with heights and beauties. H <= 1e5, B <= 1e9. We want to pull out flowers so the remaining ones are mono-increasing. What is the max total beauty we can pull out? Also heights are a permutation of size N.
Notes:
dp[x] tells us the max beauty for an increasing subsequence ending in x initialize to only 0s then iterate over each flower, use a segment tree range max query point update to apply the updates as we go
Drill Type:
Mindsolvere-read solution
Solutions:
C - Vacation
Problem Summary:
We have N <= 1e5 activities, can swim do homework or catch bugs. We have 3 arrays of size N for scores for each. Cannot repeat activity twice in a row. Max score?
Notes:
standard dp state machine space optimized 🙂
Solutions:
B - Frog 2
Problem Summary:
We have N <= 1e5 stones with heights <= 1e4, we can jump from a stone to the one on the right up to K <= 100 spaces away, and incur abs(h2-h1) cost, what is min cost to reach the end?
Notes:
same as frog 1 but N*K this time, 1d dp go left to right tells us the answer to reach stone i
Solutions:
A - Frog 1
Problem Summary:
We have N <= 1e5 stones with heights <= 1e4, we can jump from a stone to the one on the right, or two on the right and incur abs(h2-h1) cost, what is min cost to reach the end?
Notes:
standard left to right 1d dp where dp[i] tells us the answer to reach stone i
Solutions:
F - Construct a Palindrome
Problem Summary:
We have N <= 1000 nodes and M <= 1000 edges, we want to go from 1 to N on a path (can repeat), can we form a palindrome? Each node has a letter.
Notes:
I did a bfs on node pairs (node1, node2) with a triple loop on the edges and letters I think that we have n^2 nodes. And for each node it visits its edges at most N times (for every adjacent node pair) so I think we get like n^2 + m*n or something I’m not sure but this makes sense
Drill Type:
Mindsolvere-read notes / code, amortized time is interesting
Solutions:
O - Matching
Problem Summary:
We have N <= 21 men and women, we have a compatibility for every pair which is 1 or 0. Find the # of ways we can form N valid pairs.
Notes:
dp(manIndex, womanMask) looks like n * 2^n states but manIndex is derived so it is 2^n inside it, we iterate over all women indices to pair up that man with, so n * 2^n total complexity and 2^n space
Solutions:
E - Stronger Takahashi
Problem Summary:
need to move from top left to bottom right, there are walls and we can destroy a 2x2 region, minimum # of destroys needed?
Notes:
clean impl is loop on all adj cells directly, those have cost 0 if not a wall then loop on all destroyable regions like (2,1) and just push a cost+1 node for that
Drill Type:
Mindsolvere-read notes / code