Please upvote me. Need karma points to ask questions. Thanks !
Need Karma Points
SUMDIS - Editorial
PROBLEM LINK:
Author:Hanlin Ren
Testers:Sergey Kulik, Kamil Dębowski
Editorialist:Pawel Kacprzak
DIFFICULTY:
Hard
PREREQUISITES:
Divide and conquer, sweep line/segment tree
PROBLEM:
$G$ is a directed acyclic graph with $N$ vertices numbered from $1$ to $N$. There are $3$ classes of edges in $G$:
- For every $1 \leq i \leq N-1$ there is an edge $(i, i+1)$ with weight $a_i$
- For every $1 \leq i \leq N-2$ there is an edge $(i, i+2)$ with weight $b_i$
- For every $1 \leq i \leq N-3$ there is an edge $(i, i+3)$ with weight $c_i$
For any pair of vertices $s < t$, let $d(s, t)$ be the length of the shortest path from $s$ to $t$ in $G$. The task is to compute the sum of $d(s, t)$ for every $1 \leq s \lt t \leq N$.
QUICK EXPLANATION:
Use divide and conquer to remove $3$ central nodes, which disconnects the graph, solve the problem recursively into smaller graphs and combine the results into the final result.
EXPLANATION:
First of all, notice that the graph $G$ is a directed acyclic graph and has $O(N)$ edges with a very small constant.
Subtask 1
In the first subtask, we have $N \leq 10^3$ and sum of $N$ over all test cases not greater than $10^4$. This allows the most straightforward method of iterating over all vertices, and for a fixed vertex $i$, compute the sum of distances from $i$ to all other vertices $j > i$. This can be easily done in $O(N)$ time for a fixed vertex $i$ because the graph is a directed acyclic graph (see here for more details). In our case, it's even easier because the topologic order of $G$ is just $1, 2, \ldots, N$.
Subtask 2
In the second subtask, we know that there is a specific relation between weight of edges in all classes:
$b_i = a_i + a_{i+1}$
$c_i = a_i + a_{i+1} + a_{i+2}$
If we take a closer look at above equations, we can notice that if $P$ is the shortest path from $i$ to $j>i$, and $P$ uses at least one edge of the second or the third class, then there exists another path $P'$ of the same length that $P$, such that $P'$ use only edges from the first class. This is true because any edge of the second class in $P$ can be replaced by two consecutive edges of the first class without changing the length of the path. Similarly, each edge of the third class in $P$ can be replaced by three consecutive edges of the first class without changing the length of the path. Thus, we can reduce the graph to a path graph where vertices $i$ and $i+1$ are connected by an edge with weight $a_i$ and there are no other edges in the graph. Moreover, between any two vertices $i < j$ there is now exactly one path.
How to solve this simpler problem on the path graph? Well, it's pretty easy. An Edge $(i,i+1)$ for $i=1,2, \ldots, N-1$ is taken into the final result $i \cdot (N-i)$ times because it is a part of that many shortest paths connecting vertices with indices $x \leq i$ with vertices with indices $y \geq i+1$.
Subtask 3
In the third subtask, we also know something specific about relation of weight of edges from the first and the third class:
$c_i = a_i + a_{i+1} + a_{i+2}$
Using a similar reasoning as in the solution for the second subtask, we can reduce the input graph to a graph with edges only from the first and the second class. The solution for such a graph is the same as the solution for the third subtask, except the fact that one crucial step is easier to perform. Please read the description of the intended solution below to get the overall idea, and the distinction between these two solutions it also pointed out there.
Subtask 4
In the last subtask, we have the original constraints. The idea here is to use divide and conquer approach in order. Let's assume that we are solving the problem for an induced graph $G$ with vertices from range $[L, R]$ only. Clearly, the final result will be the solution for a graph with vertices in a range $[1, N]$. Now, the crucial observation comes:
Let $m$ be some vertex such that $L < m < R$. Then, if we remove vertices $m-1, m$ and $m+1$ from $G$, then we get two disconnected graphs $G_L$ and $G_R$ denoted by vertices in ranges respectively $[L, m-2]$ and $[m+2, R]$. Thus, we can solve the problem recursively for both of them, add sub-results computed for these sub-problems, and the only remaining thing to do is to compute:
- $f(l, r, m) := \sum_{l \leq i < m < j \leq r} d(i, j)$
- $g(l, r, m) := \sum\limits_{l \leq i < m-1} d(i,m-1) + \sum\limits_{l\leq i < m} d(i,m)+ \sum\limits_{m < i \leq r} d(m, i) + \sum\limits_{m+1< i \leq r} d(m+1,i)$
where $f(l, r, m)$ is the sum of all shortest paths from vertices with numbers smaller than $m$ to vertices with numbers larger than $m$, while $g(l, r, m)$ is the sum of all shortest paths to vertices $m-1$ and $m$ and from vertices $m$ and $m+1$.
The result for graph $G$ denoted by $[L, R]$ is then the sum of subresults for graphs $G_1$ and $G_2$ plus $f(l,r, m)$ plus $g(l,r,m)$.
One more thing before we take a look at how to compute values of $f$ and $g$. Notice that as often in divide and conquer approaches, we want to divide the problem into as equal (in terms of size) sub-problems as we can. Here, picking $m = (L+R)/2$ does the job because it reduces the size of the problem by a factor of $2$ every time. Moreover, when the size of a sub-problem is small enough, so $R-L+1 < C$, where $C$ is some constant, we can solve the problem with a quadratic solution described as the solution to the first subtask. This is a common technique used to speed up a solution in practice.
Now, how to compute values of $f$ and $g$ defined above? Let's start with $g$ because it's easier.
Notice, that $g$ is just a sum of three different sums. Each of them is a sum of the shortest paths to or from a fixed vertex, so a single such sum can be computed easily in $O(N)$ time by solving a standard shortest path problem in a DAG.
Now the harder part, computing $f$. Let's consider two vertices $i < m$ and $j > m$. Then, $d(i, j)$ is the smallest of the following $3$ values:
$d_1(i, j) := d(i, m-1) + d(m-1, j)$
$d_2(i, j) := d(i, m) + d(m, j)$
$d_3(i, j) := d(i, m+1) + d(m+1, j)$
Thus, we are interested, for all $i < m$ and $j > m$, how many times $d(i, m-1)$ contributes to the final result, so how many times path $d(i, m-1)$ is a part a a shortest path in all shortest paths counted in $f(l, r, m)$. Similarly, we want to count the same for $d(m-1, j)$, $d(i, m)$, $d(m, j)$, $d(i, m+1)$, and $d(m+1, j)$. We are going to show how to do it only for $d(i, m-1)$, because other cases are very similar.
Now, we are interested in how many times $d(i, m-1)$ is counted into $f(l,r,m)$, which is equal to the number of times $d_1(i, j)$ is smaller than $d_2(i,j)$ and also is smaller than $d_3(i,j)$. If any two paths, for example $d_1(i, j)$ and $d_2(i, j)$ are equal, we say that the one with smaller subscript is smaller, so $d_1(i,j)$ is smaller in this case. In other words, for a fixed node $i$, we are interested in number of $j$, such that $m < j \leq r$, and both below equations are fullfilled:
$d(i, m-1) + d(m-1, j) \leq d(i, m) + d(m, j)$
$d(i, m-1) + d(m-1, j) \leq d(i, m+1) + d(m+1, j)$
above equations can be rewriten as:
$d(m-1, j) - d(m,j) \leq d(i, m) - d(i, m-1)$
$d(m-1, j) - d(m+1,j) \leq d(i, m+1) - d(i, m-1)$
Now, if we let:
$x_0 = d(i,m) - d(i,m-1)$
$y_0 = d(i,m+1) - d(i,m-1)$
and
$x_j = d(m-1,j) - d(m,j)$
$y_j = d(m-1,j) - d(m+1,j)$
Then we are interested in the number of points $(x_j, y_j)$ in $2d$ plane, such that $x_j \leq x_0$ and $y_j \leq y_0$. This last problem can be solved with for example a sweep line algorithm, sweeping through all $O(R-L)$ points in sorted order by their $x$ coordinates and maintaining a set of all points seen so far sorted by their $y$ coordinate. It follows, that the time needed to compute $f(l, r, m)$ is $O((R-L) \cdot \log (R-L))$, and its dominated by the time of sorting the points and performing query operations to the set sorted by $y$ coordinates.
Now, we showed how to decompose a problem using divide and conquer and how to combine the results computed for subproblems with additional values, $f$ and $g$, into the final result. The total time complexity of this approach can be written as $T(N) = 2 \cdot T(N/2) + O(N \log N)$, which is equal to $O(N \log^2 N)$.
For implementation details please refer to both setter's and tester's solutions.
AUTHOR'S AND TESTER'S SOLUTIONS:
Setter's solution can be found here.
Second tester's solution can be found here.
Dynamic Programming : Create iterative solution
How do I create an efficient Dynamic Programming iterative solution if I can develop a recursive solution for the same?
Edit 1: I have seen several problems on spoj where I can design a recursive solution O(2^n) but those solutions generally time out. After looking into the solutions of the problem I found that an iterative solution with O(n^2) mostly works. So, I am just asking is there a general process to create an iterative solution from a recursive one?
FAVGAME - Editorial
PROBLEM LINK:
Author:Alexey Zayakin
Testers:Sergey Kulik, Kamil Dębowski
Editorialist:Pawel Kacprzak
DIFFICULTY:
Medium
PREREQUISITES:
Trees, dynamic programming
PROBLEM:
The goal of the problem is to complete a video Game in a few days as possible. The Game has $n$ levels numbered from $1$ to $n$ and you can play it at most $h \leq 24$ hours per day. The $i$-th level takes $t_i \leq h$ hours to complete. The levels are structured in a tree $T$. It means that the level $1$ is the root of the tree and the only unlocked level available to play at the beginning. Every other level $i$ has unique level, its parent in the tree denoted as $parent_i$, such that completing level $parent_i$ unlocks level $i$ making it available to play. The game is completed when all its levels are completed. Moreover, the process of completing the game looks as follows:
- There is a stack $S$ initially containing only the level $1$
- You pop the topmost level $x$ out of the stack
- You spends $t_x$ hours to complete level $x$ and you must complete it during a single day, which means that if there are not enough hours to complete level $x$ on the current day, you cannot start it on that day.
- After completing level $x$ some $m_x$ new levels get unlocked
- You place all the $m_x$ unlocked levels on the top of the stack $S$ in an arbitrary order
- If stack $S$ is empty, the Game is considered completed, otherwise you go back to the step $2$
The task is to find the minimum number of days needed to complete the Game.
QUICK EXPLANATION:
Use dynamic programming to compute for each vertex $v$ the minimum number of days needed to complete all levels in $v$'s subtree when you start on day $1$ in $v$ and have already worked $p$ hours on that day.
EXPLANATION:
First and major observation we can make is to notice that each valid play, i.e. the order in which levels of the game are unlocked, corresponds to DFS order on $T$. Thus, the problem is reduced to finding DFS order which yields the smallest cost of visiting all $N$ nodes of $T$.
Subtask 1
In the first subtask, we have $N \leq 9$, which allows totally brute-force solution. Notice that there are no more than $N!$ possible DFS orders of $T$, so one can generate all $N!$ permutation of the nodes, take only the ones describing valid DFS orders, and for each such sequence, compute the number of days needed to complete the game unlocking levels in the order given by the sequence. The result is the minimum result among all such valid DFS sequences. The time complexity of this method for a single test case is $(N! \cdot N)$.
Subtasks 2, 3, 4
Approaches for subtasks 2, 3 and 4 are based on dynamic programming approach, so let's describe the idea first. Just to recall, notice that $h \leq 24$ and each node has at most $10$ children. Both these constraints are very important here.
Let $dp_{v, p}$ be a pair $(a, b)$ denoting that when we start processing $v$'s subtree on the first day and have already worked $p$ hours that day, then $a$ is the minimum number of additional days, besides the first day, to complete the whole $v$'s subtree and $b$ is the minimum number of hours we have to work on the last day in such optimal solution. Now, by this definition, $dp$ functions captures all information we need, and the result to the problem is the resulting number of days in $dp_{1}{h}$, because $1$ is the root of the tree and completing its subtree means that the whole game is completed, and its always not worse to work as many hours on the first day as possible.
Now, notice that for fixed $v$ and $p$, the value of $dp_{v, p}$ can be easily computed when we only know the best order in which we should complete subtrees of children of $v$. More specifically, if we know such best order, then we first complete level $v$, because it has to be completed before any other levels in $v$'s subtree, and then we solve the problem recursively for all $v$'s children. Next, we just compute the value of $dp_{v,p}$ straight away by accumulating, in a deterministic way, values computed for $v$'s children in such an order. Thus, the problem is reduced to just computing the best order of processing subtrees of $v$'s children.
Subtask 2
In the second subtask, there is an additional constraint on the number of children of a node, and we know that each node has at most $2$ children. This allows for a fixed node $v$ to just check at most $2! = 2$ orders of completing subtrees of $v$'s children and assign the smallest result to $dp_{v,p}$.
Subtask 3
In the third subtask, we have $N \leq 100$ and $h \leq 8$. These constraints allow to use the intended method for the original constraints but just implemented in not an optimal way. For example, one can capture additional, not necessary information in states of $dp$, resulting in higher complexity of the solution than the intended one.
Subtask 4
In the fourth subtask, we have the original constraints, and the only thing left to do is to show how for a fixed $v$ and $p$, compute the best order of completing subtrees of $v$'s children resulting in the smallest value of $dp_{v,p}$. Just to recall, we know that $v$ has at most $10$ children, so there are at most $10!$ possible such orders, but, since this number is quite big, checking just any of them explicitly is unacceptable.
However, a quite common optimization can be used here. We can avoid iterating over all permutations of children and instead iterate over all subsets of them. For a fixed node $v$, let $f_{mask, p}$ be a pair $(a, b)$ denoting that when we start processing $v$'s subtree on the first day and have already worked $p$ hours that day, then $a$ is the minimum number of additional days, besides the first day, to complete level $v$ and subtrees of $v$'s children included in the $mask$, and $b$ is the number of hours we have to work on the last day in such optimal solution. Then, set $mask$ can be implemented as a binary number of length $m_v$, where $1$ at the $i$-th position in $mask$ denotes that the $i$-th children is included into the set. Now, we can just iterate over all $masks$ and extend a solution for a fixed $mask$ to a $mask_{new}$ having one more subtree completed than $mask$. Then, the value of $dp_{v,p}$ is just the value of $f_{mask_{full}, p}$, where $mask_{full}$ denotes a set of all children of $v$.
The overall time complexity of this method is $O(N \cdot h \cdot 2^{10})$. For implementation details of this exact method please refer to setter solution.
AUTHOR'S AND TESTER'S SOLUTIONS:
Setter's solution can be found here.
First tester's solution can be found here.
Second tester's solution can be found here.
ANUMLA - Editorial
PROBLEM LINK:
Author:Anudeep Nekkanti
Tester:Constantine Sokol
Editorialist:Florin Chirica
DIFFICULTY:
Easy
PREREQUISITES:
greedy, heaps (or STL multiset)
PROBLEM:
You have an unknown set of length N. We take all 2 ^ N subsets of it and sum elements for each subset. Given what we obtained, restore a possible initial set.
QUICK EXPLANATION
We build our solution step by step. Each step we take smallest element from sums. Suppose we’re at step i and we found element x[i]. We should erase now from sums all sums formed by x[i] and a non-empty subset of {x[1], x[2], ..., x[i – 1]}.
EXPLANATION
Let’s call all 2^N sums sumSet. Also, let’s call a possible solution valueSet (making sum of all subsets of valueSet, you should obtain sumSet). The problem says there is always a possible solution. We’ll implement sumSet as a multiset from C++. This container allows following things, which will be needed later: find/delete an element and keep the set in increasing order. We’ll note first element from current sum set as sumSet[1], second element as sumSet[2] and so on. Let’s read all numbers from the input and add all of them in multiset sumSet.
Smallest element from sumSet is always 0 (and it corresponds to empty subset). It does not give us any information, so let’s erase it from the set and move on. What’s smallest element now? Is it an element from valueSet? Is it a sum of a subset of valueSet?
There exists at least one element from valueSet equal to smallest element from sumSet. Why? Suppose first element of sumSet is a sum of other elements of valueSet. sumSet[1] = valueSet[k1] + valueSet[k2] + .... where k1, k2, ... are some indexes.
Since numbers are positive, we get that valueSet[k1] <= sumSet[1], valueSet[k2] <= sumSet[1] and so on. Since sumSet[1] is smallest element possible, we can only get that valueSet[k1] = sumSet[1], valueSet[k2] = sumSet[1] and so on.
This means at least one element from valueSet will have value equal to sumSet[1]. We’ve found one element from valueSet. Let’s add it to valueSet (we build the set incrementally) and erase it from sumSet. Let’s move now to our new sumSet[1] element (smallest element from sumSet, not deleted yet). We can follow same logic from above and see that sumSet[1] is a new element from valueSet. Let’s add it to valueSet and erase it from sumSet.
We move once again to sumSet[1]. Now, we have a problem. It can be one of following 2 possibilities:
sum of subset {valueSet[1], valueSet[2]}
a new element of valueSet.
Case b) is ideal, because we found one more element of valueSet. What to do with case a)? We know sum valueSet[1] + valueSet[2]. So we can simply erase it from sumSet, before considering sumSet[1]. Then, only case a) is left, so we find valueSet[3]. We erase now valueSet[3] from sumSet (I know, it becomes boring already, I’ll finish in a moment :) ).
It’s more tricky now what can be sumSet[1]. It can be one of following: valueSet[3]+valueSet[1], valueSet[3]+valueSet[2], valueSet[3]+valueSet[1]+valueSet[2]. We can fix this by erasing all those elements from sumSet before considering sumSet[1]. Once again, we’re left with valueSet[4]. Let’s note that all sums that should be erased contain a valueSet[3] term and a non-empty subset of {valueSet[1], valueSet[2]}. Sums of subsets of {valueSet[1], valueSet[2]} are already erased in previous steps.
Generalizing the algorithm
Let’s generalize the algorithm. Suppose you want to calculate valueSet[n]. We need firstly to erase from set a combination of valueSet[n – 1] and a non-empty subset of {valueSet[1], valueSet[2], ..., valueSet[n – 2]}. Then, the smallest element is valueSet[n].
We can keep an additional array subsets[] representing all subset sums obtained from {valueSet[1], valueSet[2], ..., valueSet[n – 2]}. Then, at step of calculating valueSet[n], we need to erase subsets[j] + valueSet[n – 1] from our sumSet. Now, valueSet[n] is calculated.
The new subset sum list will be the old one plus the one that contains valueSet[n – 1]. So, after we calculate valueSet[n], we update subsets with all values valueSet[n – 1] + subSets[j]. We run this algorithm as long as there is at least one element in sumSet.
Time Complexity
Each element is added in the multiset once and erased once. Hence, the complexity is O(2 ^ N * log(2 ^ N)) = O(2 ^ N * N).
AUTHOR'S AND TESTER'S SOLUTIONS:
BANDMATR - Editorial
PROBLEM LINK:
Author:Praveen Dhinwa
Testers:Sergey Kulik, Kamil Dębowski
Editorialist:Pawel Kacprzak
DIFFICULTY:
Simple
PREREQUISITES:
Basic matrix knowledge, basic programming
PROBLEM:
The the bandwidth of a square matrix $A$ is the smallest non-negative integer $k$, such that for all $|i-j| > k$ $A[i] = 0$.
For a given binary square matrix $A$ with $N$ rows and $N$ columns, the goal is to a rearrange its elements to get a matrix with the smallest bandwidth. The answer for the problem is the value of the smallest bandwidth we can get that way.
QUICK EXPLANATION:
Put all $1$'s on the closest diagonals to the main diagonal and compute the result.
EXPLANATION:
Subtask 1
In the first subtask we know that $N$ is at most $100$. We can take advantage of this fact and solve the problem as follows. First, notice that the resulting bandwidth is an integer in a range $[0, n-1]$. Now, we can iterate over all possible bandwidth candidates starting from the smallest one. For a fixed candidate $B$, we check if the number of $1$'s in $A$ is not greater than the number of cells $A[i][j]$ for which $|i-j| \leq B$. If it's the case, then we return $B$ as the answer because then we can put all $1$'s into these cells, so $B$ it is the smallest integer fulfilling the condition. Notice that for a fixed $B$ the check can be performed in $O(N^2)$ time, and since there are $O(N)$ values of $B$ to check, then the total time complexity of this method is $O(N^3)$.
Subtask 2
First of all, let's notice that if we take any of the $2 \cdot N - 1$ diagonals of the matrix, and any element on this diagonal, let's say $A[i][j]$, then for each other element $A[i_1][j_1]$ on this diagonal, we have $|i-j| = |i_1-i_2|$.
Thus each diagonal can be defined by a value $x = |i-j|$ where $A[i][j]$ is any element on this diagonal.
Moreover, there is just one diagonal with $x=0$, the main diagonal. Next, there are exactly $2$ diagonals with $x=1$, the ones adjacent to the main diagonal. In general, for $0 < y \leq N-1$ there are exactly two diagonals with $x=y$ and they are the diagonals in distance $y$ from the main diagonal, where the distance from diagonal $d$ to the main diagonal is the number of other diagonals between them.
Based on the following observation, if we want to arrange elements of $A$ in its cells in such a way that $k$ for which for all $|i-j| \gt k$, $A[i][j] = 0$ is minimal, the best we can do is to place all $1$'s in cells on diagonals as closest to the main diagonal as possible. Thus we can iterate over diagonals in order of their distances to the main diagonal and fill them with $1$'s until all ones are used. Then the result is the largest integer $k$ for which $1$ was put onto a diagonal with $x=k$ during that process or $0$ if there are no $1's$ in $A$.
AUTHOR'S AND TESTER'S SOLUTIONS:
Setter's solution can be found here.
First tester's solution can be found here.
Second tester's solution can be found here.
Editorialist's solution can be found here.
Multi-dimensional Dynamic Programing
How I will know in this problem Multi-dimensional dp is used ?
SCHEDULE - Editorial
PROBLEM LINK:
Author:Hasan Jaddouh
Testers:Sergey Kulik, Kamil Dębowski
Editorialist:Pawel Kacprzak
DIFFICULTY:
EASY
PREREQUISITES:
Binary search
PROBLEM:
For a binary string $A$, let's define a block as a substring of $A$ containing either only $1$'s or only $0$'s, so $111$ and $0$ are blocks, while $10$ and $0010$ are not. Moreover, let a major block be a block of $A$, such that no block in $A$ is longer that it and $L$ be the length of a major block of $A$. Notice that there can be many major blocks, but all of them have the same length.
Then the problem can be reformulated as follow: for a given binary string $A$ of length $N$ and integer $K$, we have to return the minimum $L$ (the length of a major block) that we can get by performing at most $K$ bit flips on $A$.
For example, if $A = 11100$ and $K=1$, the best we can do is to either flip the first or the second bit to get for respectively $01100$ and $10100$. In both these strings, $L$ is $2$, which is the best we can get in this case.
QUICK EXPLANATION:
First, check if getting $L=1$ is possible. If yes the problem is solved, otherwise, perform a binary search on the result checking if getting $L=M$ is possible in linear time.
EXPLANATION:
First of all, let's take a closer look at the constraints. It is said that $K \leq 10^6$, but since also $N \leq 10^6$ and there is no point of flipping a single bit more than once, we can rewrite the constraint as $K \leq N$.
Subtask 1
In the first subtask $N \leq 10$, so one can generate all possible strings we can get by performing at most $K$ flips on $A$, and compute the smallest $L$ among them. This is possible because there are at most $2^N$ such strings and computing $L$ for a single string takes $O(N)$ time. Thus the overall time complexity of solving all test cases will be $O(T \cdot 2^N \cdot N)$, which is completely fine for these constraints and $T \leq 11000$.
Subtask 2
In the second subtask we have $N \le 10^6$, so the problem has to be solved in a clever way. The crucial observation is that for any $L$ and any block of $A$ with length $M$, $\lceil M / (L+1) \rceil$ flips are necessary to convert that block into a substring without blocks of length greater than $L$, and we can perform exactly that many flips to do that.
For example, if we have a block of length $5$, $00000$, and $L=2$, we flip its bits with indices $L+1, 2 \cdot (L+1), 3 \cdot (L+1) \ldots$, so in this particular case, we flip only its third bit to get $00100$. Similarly, if we have a block of length $6$, $000000$, and $L=2$, we flip its third and sixth bits to get $001001$.
Thus it looks like we can perform a binary search for the answer and for a fixed $M$, check if we can transform all the blocks in $A$ into block of length at most $X$ using at most $K$ flips by just iterating over all blocks in $A$ and computing the sum of needed swaps for all of these blocks. Notice that binary search is correct here, because if it is not possible to use at most $K$ swaps to get $A$ with $L=X$, then it is also not possible to use at most $K$ swaps to get $A$ with $L \lt X$. This will result in $O(N \cdot \log N)$ time complexity for a single test case, but since the sum of $N$ across all test cases is at most $10^6$, this will run fast enough. However, we are not finished yet, because there is a tricky case to handle.
Notice that when we divide $A$ into blocks, the blocks alternate in such a way that after a block consisting of $0$'s there is a block consisting of $1$'s, then one consisting of $0$'s again and so on. The observation we made says that for a block of length $M$, $\lceil M / (L+1) \rceil$ flips are necessary and sufficient to convert this block into blocks of sizes at most $L$. It is true for an isolated block, however, since in some cases we are forced to flip the first or the last bit of such block, that may ruin our solution because that bit can create another block with adjacent blocks.
Let's take a closer look where this situation can happen, so in what cases we are really forced to flip either the first of the last bit of a block? As mentioned above, for a block of length $M$ and a fixed $L$, we can flip bits with indices $L+1, 2 \cdot (L+1), 3 \cdot (L+1) \ldots$. It follows that we are flipping its last bit if $M \mod (L+1) = 0$. However, if this happens and $L \gt 1$, we can always flip bits with indices $L, 2 \cdot L, 3 \cdot L, \ldots$ and we avoid flipping the first and the last bits, which caused the problem. But what happens when $L = 1$? Well, then we cannot use that trick, however, this case is easy to handle: at the beginning, we can just check if $A$ can be transformed using at most $K$ flips to get $L=1$. Notice that there are just $2$ possible strings of given length with $L=1$, either a sequence of alternating $0$'s and $1$'s starting with $0$ or the same but starting with $1$. If this is the case we are done. Otherwise, we use binary search described above searching for the answer in a range $[2, N]$. For implementation details, please refer to multiple solutions linked below.
AUTHOR'S AND TESTER'S SOLUTIONS:
Setter's solution can be found here.
First tester's solution can be found here.
Second tester's solution can be found here.
Editorialist's solution can be found here.
What will happen internally when we define a class and its object?
Please tell me - What will happen internally when we define a class and its object?
query regarding new prize
Hello everyone...few days back I enquired admin about 100% attendance reward listed in new prize category. I want to know whether partial score will be included in solving a problem(at least 1 problem) like in long challenge and lunchtime?? Please let me know...thanks
Android Development
I want to learn Android Development. I tried official site but it's hard to learn from there. Does anyone know from where I can access video lectures or step-by-step tutorials to learn android dev.?
KGOOD - Editorial
PROBLEM LINK:
Author:Kevin Atienza
Testers:Sergey Kulik and Vasya Antoniuk
Translators:Sergey Kulik (Russian), Team VNOI (Vietnamese) and Hu Zecong (Mandarin)
Editorialist:Kevin Atienza
DIFFICULTY:
Easy
PREREQUISITES:
Strings, Greedy algorithms
PROBLEM:
A string is $K$-good if for every two letters in the string, if the first appears $x$ times and the second $y$ times, then $|x - y| \le K$. Given $K$ and a string $w$, what is the minimum number of letters to remove to make $w$ $K$-good?
QUICK EXPLANATION:
For every $m$, define $F[m]$ as follows:
- Remove every letter that appears $< m$ times.
- For every letter that appears $> m+K$ times, remove just enough letters so that it appears exactly $m+K$ times.
- Let the number of removed letters be $F[m]$.
The answer is then the smallest among $\{F[1], F[2], \ldots, F[N]\}$. To compute this quickly, simply precompute the letter frequencies in $w$ beforehand, and operate on that array when computing $F[m]$.
EXPLANATION:
Let's use the notation $w_{(c)}$ to denote the number of appearances of the letter $c$ in the string $w$.
$K$-goodness
By definition, a string is $K$-good if for every two characters $c$ and $d$, $\left|w_{(c)} - w_{(d)}\right| \le K$. But for a given string $w$, the value of $\left|w_{(c)} - w_{(d)}\right|$ is maximized if $c$ and $d$ are the most and least occurring characters in $w$ (or vice versa). Thus, we have a potentially simpler criterion for telling whether a string is $K$-good:
If $c$ and $d$ are the most- and least- occurring characters in $w$, then $w$ is $K$-good if and only if $w_{(c)} - w_{(d)} \le K$.
Notice that we have removed the absolute value because $w_{(c)} \ge w_{(d)}$.
Removing letters
This immediately gives us a greedy algorithm for turning $w$ into a $K$-good string in a few letter removals:
- Compute the frequency counts for each of the 26 letters.
- Find the least-occurring character $d$. (Note that we only consider characters that actually appear in $w$, that is, whose frequency counts are positive.)
- For every character $c$ appearing more than $w_{(d)} + K$ times, remove $w_{(c)} - (w_{(d)} + K)$ instances of $c$.
Clearly this algorithm yields a $K$-good string if you use our criterion above. Unfortunately though, it doesn't yield the minimum number of removals! For example, consider the input boooooooooo 0
. The algorithm above will have us remove $9$ instances of the letter 'o
', yielding the string "bo
" which is $0$-good. But it's possible to do it with just $1$ removal: just remove the 'b
'!
So how do we fix this? Clearly, we can't assume that the least-occurring character in $w$ will appear in the final string. In fact, it isn't obvious what the minimum frequency count must be in the final string. So what do we do? We just try them all!
Our adjusted algorithm would be:
- Decide on the minimum frequency count on the final string, and call it $m$.
- Remove every letter that appears less than $m$ times.
- For every letter $c$ that appears more than $m + K$ times, remove $w_{(c)} - (m + K)$ instances of $c$.
The answer is then the minimum number of removals for all such values $m$ in the range $m \in [1,N]$. Now, clearly this is correct, but is it fast enough? Well, it depends on your implementation. Obviously, if you process the string for every $m$, you'll get an $O(N^2)$ running time which is pretty bad. But thankfully, we can reduce it by noticing that every iteration of the above procedure only requires the frequency counts of all the letters! By computing the frequency counts just once and then using that array instead, we get a running time of $O(N)$!
Here's a pseudocode:
// compute counts
counts['a'..'z'] // initialized to zero
for i=0..|w|-1:
counts[w[i]]++
// compute answer
answer = N
for m=1..N:
current = 0
for c='a'..'z':
if counts[c] < m:
current += counts[c]
else if counts[c] > m + K:
current += counts[c] - (m + K)
if answer > current:
answer = current
print answer
Optimization
We can actually still optimize the algorithm above, by noticing that we don't have to try all values $m$ in the range $[1,N]$. Instead, we only try the $m$ values that are equal to some $w_{(c)}$!
Why is that? Suppose we chose a value $m$ and it's not equal to any $w_{(c)}$. Then if we instead choose $m+1$, then there aren't any additional characters whose frequency counts are $< m+1$, so we don't have to remove any additional characters. However, we potentially save a few removals, particularly those whose frequency counts are $> m+K$! Thus, the result of the procedure above for $m$ cannot be strictly less than its result for $m+1$, so it follows we don't have to check $m$ if it's not equal to any $w_{(c)}$!
With this optimization, the number of times we perform the procedure reduces from $N$ to (at most) $26$! To formalize the optimization, notice that our original $O(N)$ algorithm actually runs in $O(N\alpha)$ where $\alpha$ is the size of the alphabet. This optimization reduces that to $O(N + \alpha^2)$, which is usually better because $N \gg \alpha$ usually!
Here's a pseudocode:
// compute counts
counts['a'..'z'] // initialized to zero
for i=0..|w|-1:
counts[w[i]]++
// compute answer
answer = N
for d='a'..'z':
m = counts[d] // consider only the relevant m's
current = 0
for c='a'..'z':
if counts[c] < m:
current += counts[c]
else if counts[c] > m + K:
current += counts[c] - (m + K)
if answer > current:
answer = current
print answer
Time Complexity:
$O(N)$
AUTHOR'S AND TESTER'S SOLUTIONS:
Why do I get a SIGFPE?
I keep getting SIGFPE error when i try to run my program. Why so?
MIXFLVOR - Editorial
PROBLEM LINK:
Author:Hasan Jaddouh
Testers:Kamil Debowski
Editorialist:Hasan Jaddouh
Difficulty:
Medium-hard
Prerequisites:
Gaussian-elimination, two pointers, two stacks trick
Problem Statement:
You are given a sequence of N elements, each element has a cost and a value, you want to buy a consecutive sub-sequence such that their total cost does not exceed K and and to maximize the XOR that you can get from subset of values of elements that you bought
Explanation:
We will start of discussing special cases some useful techniques then we will mix them together to provide the full solution for this problem.
Finding a subset of numbers that have maximum XOR
Say that we have a sequence of numbers of we want to pick a subset of them having maximum possible XOR.
Let L(S) be a set of all numbers that can be result of XOR of any subset of S including empty one, for example L({1, 5}) = {0, 1, 4, 5}
what want we want to find is maximum number of L(S) where S is the set of given numbers.
Lemma: Let S be a set of numbers and let S' be a set of numbers that is resulted from picking two different numbers A and B from set S and replacing them with A and A xor B, we have L(S) = L(S').
for example if S={4, 6, 7} one possibility of S' is {4, 4 xor 6, 7}
proof: Let X be an element from L(S), let's write X as the xor of elements of S, (i.e. X=X1 xor X2 ... Xk; where Xi is element of S)
now we have 2 cases:
1- B is not an element of sequence Xi, then X is obviously element of L(S') because all Xi are present in S'
2- B is an element of sequence Xi, then we can write X as xor of subset of S' by removing B from sequence Xi and adding both A and A xor B to sequence Xi
so the above lemma tells us that we can apply this operations as many times as we want and we still have an equivalent sequence.
Lemma2: Let S be a set of numbers and S' be a set of numbers resulted by removing 0 from S if it exists, then L(S) = L(S')
proof: 0 is neutral in operation XOR
with those two lemmas we want to change our sequence into a sequence such that no two elements have same index of Most Significant Bit (MSB), we start by an empty set S and add the elements of given sequence one by one into this set Let's say currently we want to add the number C but before we add it we make sure that no element V in the set have index of its MSB same as the number of want to add, if there's one such element in the set then we xor C by V (i.e. C become equal to C xor V) then we check again until C becomes 0 in this case we don't add it at all because of second lemma, or there's no longer a number of the set S with same index of MSB as C then we add C into the set
now we have reduced our sequence into a sequence such that no two elements have same index of MSB, note that this sequence have at most 30 elements because all numbers are less than 109
after that we can greedily find maximum xor subset in this way:
We start with answer ANS=0 then we iterate over all indices i from 29 to 0, now if there's an element X in our sequence with MSB index equal to i and i-th bit in ANS is 0, then we xor element X to the answer (i.e. ANS = ANS xor X), in the end of this process the answer is ANS
note with this solution it's easy to support adding new elements to the sequence
You can see more details how to support adding new element to sequence and getting the max xor subset from setter's code
struct Gauss{
int arr[31];
int len;
Gauss(){
len=0;
}
void add(int x){
for(int i=0;i<len;i++){
if( (arr[i]^x)< x) // it's true when index of MSB of arr[i] is 1 in x
x=arr[i]^x;
}
if(x!=0){
arr[len++]=x;
for(int i=len-1;i>0;i--){ // keep the list sorted in decreasing order, helpful to find the max
if(arr[i]>arr[i-1]){
swap(arr[i],arr[i-1]);
}
}
}
}
int getMax(){
int ret=0;
for(int i=0;i<len;i++){
if((ret^arr[i]) > ret){ // it's true when index of MSB of arr[i] is 0 in ret
ret= ret^arr[i];
}
}
return ret;
}
};
Supporting Deleting latest-added element
we can easily support adding new elements and deleting the element which is added most recently by using stack such that each element of the stack is the sequence of elements (remember each sequence is at most 30 elements)
whenever we want to add new elements we copy the sequence in top of stack and add to it the new element then we push it to the top of stack
whenever we want to delete the last added element we just pop the top element from the stack
trick: making a queue using two stacks
We can make a queue using two stacks in the following way:
one stack is header forward and the other is backward, so let's name them forward and backward stacks
Whenever we want to add new element to queue we add it to top of forward stack
Whenever we want to pop earliest added element from queue we just pop the top element from backward stack, if backward stack is empty then we move all elements from forward stack to backward stack one by one, so their order will be reversed
here's a code example:
struct queue{
stack<int> forward,backward;
void push(int x){
forward.push(x);
}
int pop(){
if(backward.empty()){
while(!forward.empty()){
backward.push(forward.top());
forward.pop();
}
}
if(backward.empty()){
cout<<"error: queue is empty";
return 0;
}
int ans=backward.top();
backward.pop();
return ans;
}
};
supporting deleting earliest-added element from the sequence
We can implement similar trick by using two stacks of sequences to make a queue of sequences, thus we can delete earliest-added element, whenever we want to find maximum answer we need to merge the top of the two stacks, since each of the top sequences has at most 30 numbers then we can simply add numbers of one sequence to another one by one
full solution
now we are ready to describe the full solution to this problem, we use two pointers to point on the current segment every time we increase the left pointer by one we try to increase right pointer until we can't afford the next element then we get the maximum, increasing right pointer by one means we add new element to our queue, increasing left pointer by one means we are poping earliest-added element from queue
time complexity is O(log(109)) every time we increase right pointer by one and whenever we want to find maximum xor subset we need to merge tops of two stacks and this would be O(log2(109)), so overall complexity is O(N log2(109))
Author's and Tester's Solutions:
TLG - Editorial
PROBLEM LINK:
Author:ADMIN
Editorialist:SUSHANT AGARWAL
DIFFICULTY:
EASY
PREREQUISITES:
Basic looping,Arrays
PROBLEM:
At the end of each round the leader and her current lead are calculated. Once all the rounds are over the player who had the maximum lead at the end of any round in the game is declared the winner.
EXPLANATION:
Create two arrays(Player1-Stores the scores of player 1 in all the rounds)[a1,a2,a3....an] and (Player2-Stores the scores of player 2 in all the rounds)[b1,b2,b3...bn].
Create a third array "Lead" such that the i'th element of Lead is ((a1+a2...+ai) - (b1+b2...bi)). Create a fourth array "modulus lead" such that the i'th element of this array is the modulus of the i'th element of "Lead".
Find the maximum element of "modulus lead".This is the maximum lead attained by the winner.If the element in the corresponding position of "lead" is positive then player 1 is the winner,otherwise player 2 is.
EDITORIALIST'S SOLUTION:
Editorialist's solution can be found here.
CHEFVOTE - Editorial
PROBLEM LINK:
Author:Praveen Dhinwa
Tester:Kevin Atienza
Editorialist:Kevin Atienza
PREREQUISITES:
Graphs, ad hoc, digraph realization
PROBLEM:
Each person votes for another person. Let $c_i$ be the number of people who voted for $i$, for $1 \le i \le n$. Find a possible voting (i.e. who each person voted) that will match the $c_i$s, or report that it is impossible.
For those who are curious, we can translate this into a graph problem: Given $c_i$ for $1 \le i \le n$, find a simple directed graph of $n$ nodes where each node has an outdegree of $1$ and an indegree of $c_i$, or report that it is impossible. The terms I used in the previous sentence are pretty standard and I'm sure you can search them online if you're unfamiliar :)
QUICK EXPLANATION:
If $\sum_i c_i \not= n$ or $\max_i c_i = n$, it is impossible. Otherwise, it can be shown to be possible.
There are many possible constructions of the voting itself, but here is a simple one:
- Let $F[i]$ be the person who $i$ voted. Assign $F[i]$ in any way to satisfy the $c_i$ (it's easy to do this), allowing people to vote for themselves for now.
- Let $b$ be the number of people who voted for themselves. If $b = 0$, then we are done.
- If $b \ge 2$, then take all such people and set them all in a cycle among themselves. After this, we are done.
- Finally, if $b = 1$, then there is only one person who voted for himself. Let that be person $i$, i.e. $F[i] = i$. Let $j$ be another person such that $F[j] \not= i$ (we can show that such a person always exists). Then swap $F[i]$ and $F[j]$. After this, we are done!
EXPLANATION:
There are $n$ voters and $S := \sum_i c_i$ votes. Each person votes exactly once, hence for any valid voting, we must have $n = S$. Therefore, if $n \not= S$, then we immediately output $-1$ (impossible), and in the following, we assume $n = S$.
If $n = S$, it is easy to find and voting that satisfies the $c_i$s. However, it is possible that in the assignment we got, some people voted for themselves, and so our goal is to find a voting without any self-votes.
Let's handle first the case where a self-vote is unavoidable: if $\max_i c_i = n$, it follows that there is exactly one nonzero $c_i$, and its value is $n$. Thus, all $n$ people voted for $i$, so a self-vote from $i$ to $i$ is unavoidable. In this case, we also immediately output $-1$.
The remarkable thing is that in all other cases, there is a solution! We will describe a few possible constructions here.
The (elegant) author's solution
The author's solution starts from any voting satisfying the $c_i$s, but possibly with self-votes. Let $F[i]$ be the person who $i$ voted. We will try to amend the assignment to remove the self-votes while still maintaining the other requirements.
Let $b$ be the number of people who voted for themselves.
If $b \ge 2$, then we pick two such people $i$ and $j$, and have them vote each other, i.e. set $F[i] = j$ and $F[j] = i$. It can be seen that this does not violate the $c_i$ constraints, but it reduces $b$ by $2$, so we do this step $\lfloor b/2 \rfloor$ times until $b$ becomes either $0$ or $1$. If $b = 0$, then we are done :)
Finally, if $b = 1$, then there is only one self-vote. Let that be person $i$, i.e. $F[i] = i$. Let $j$ be another person such that $F[j] \not= i$ (we will show that such a person always exists), and let $k := F[j]$ (which is not equal to $i$ and $j$). Then swap $F[i]$ and $F[j]$, i.e. set $F[i] = k$ and $F[j] = i$. It can be seen that this does not violate the $c_i$ constraints, but it reduces $b$ to $0$, and we're done :)
Why does the person $j$ in the previous paragraph exist? Well, if it didn't, then all people $j$ would have $F[j] = i$. This means that $c_i = n$, but we already excluded that case :)
The correctness of this algorithm easily follows from the things said above. This algorithm can be implemented in $O(n)$ (but more naïve $O(n^2)$ or $O(n^3)$ implementations also pass).
Note that in the case $b \ge 2$, we can replace the $\lfloor b/2 \rfloor$ steps above with a single step: just set the $b$ people in a cycle amongst themselves, i.e. if $i_1, i_2, \ldots, i_b$ are the people with self-votes, then set $F[i_1] = i_2$, $F[i_2] = i_3$, ... $F[i_{b-1}] = i_b$ and $F[i_b] = i_1$.
The editorialist's solution
Here we describe the editorialist's solution which is not as simple as the author's solution, but you may still find interesting nonetheless :) This just shows that there really are a lot of possible solutions to this problem.
First, if $\max_i c_i = 1$, then it can be seen that $c_1 = c_2 = \cdots = c_n = 1$, so we can just make a cycle among the $n$ people.
Otherwise, sort the people according to $c_i$. let the sorted order of the people be $s_1, s_2, \ldots s_n$, i.e. $c_{s_1} \le c_{s_2} \le \cdots \le c_{s_n}$ (note that $1 < c_{s_n} < n$). First, have $s_n$ vote for $s_{n-1}$. Now, iterate $i$ from $n-1$ to $1$, and for each $i$, assign $s_i$ to some person later in the list $s_j$ (i.e. $i < j$) such that the number of people we've currently assigned to vote for $s_j$ is still less than $c_{s_j}$. It can be shown that such a person always exists.
Now, why is the algorithm above correct? First, we obviously don't create any self-votes (assuming the person described above always exists). Second, $c_{s_{n-1}} > 0$, because otherwise, we will have $c_{s_n} = n$, which we already excluded. Moreover, we only assign a vote to some person $k$ if it will not exceed the desired number of votes $c_k$. Finally, since $\sum_i c_i = n$, we see that the final number of votes to each person are correct!
We are left with proving that the person $s_j$ above exists. To do so, we only need to prove the following fact: For any $1 \le i < n$, we have $$c_{s_{i+1}} + c_{s_{i+2}} + \cdots + c_{s_n} > n-i$$ This can be easily proven by induction and handling two cases: $c_{s_i} = 0$ and $c_{s_i} \not= 0$.
Now, given that claim, we can easily prove the existence of the person $s_j$ by noting that at each iteration $i$, there would not have been enough people later than $s_i$ to exhaust all the desired votes of the later people, so there is always a person $s_j$ which we can assign $s_i$ to!
The time complexity of this algorithm is $O(n \log n)$ dominated by the sort, but can be reduced to $O(n)$ by using counting sort.
Another Solution using Max-Flow
This part is taken from fauzdar65's comment in the thread.
Create two nodes for each of the $n$ persons, plus two more nodes: a sink and a source. We add edges from the source to each node in the first set, each with capacity $1$, since $1$ vote is available to each person.
We also add edges from each node from the second set to the sink, and the capacity of each would be the number of votes the person corresponding to that node got, i.e. $c_i$.
We also add edges from nodes from the first set to nodes from the second set, each with capacity $1$, but we don't add edges to nodes representing the same person since a person can't vote for themselves.
Finally, compute the maximum flow in this graph. It should be equal to $n$ if a solution is possible. A possible solution can then be recovered by checking the flow from nodes from the first set to the second.
Time Complexity:
$O(n^3)$, $O(n^2)$, $O(n \log n)$, or $O(n)$
AUTHOR'S AND TESTER'S SOLUTIONS:
How to find the number of set bits in large numbers ?
By 'Large', I mean numbers containing up to 10^4 digits.
I have tried doing it by converting the number to binary, digit by digit (representing numbers as a vector of bits), so I multiply the current result by 10 and add the next digit, which I have done by adding two numbers, left shifted 3 times and 1 time(because N*10 = N<<3 + N<<1) and then wrote a function that adds two binary numbers represented this way, and then add the next digit. But its too slow.
What are karma points?
I am new to this karma system, Can you explain me why is it called so? What has karma points got to do with contribution?
feb. long challenge 2017
Just saw video tutorial and tried to implement MFREQ question... can anyone tell me what am I missing at? here is my code:
Please help me...include <bits stdc++.h="">
using namespace std;
int main() {
int n,m; cin>>n>>m; long long a[n],left[n],right[n]; for(int i=0;i<n;i++) cin>>a[i]; for(int i=0;i<m;i++){ int l,r,k; cin>>l>>r>>k; left[0]=0; for(int i=1;i<n;i++) { if(a[i]==a[i-1]) left[i]=i-1; else left[i]=i; } right[n-1]=n-1; for(int i=n-2;i>=0;i--) { if(a[i]==a[i+1]) right[i]=i+1; else right[i]=i; } for(int i=0;i<n;i++) cout<<left[i]<<" "; //left array cout<<endl; for(int i=0;i<n;i++) cout<<right[i]<<" "; //right array int mid=(l+r)/2; if((right[mid]-left[mid])>=k) // not getting this condition cout<<a[mid]<<endl; else cout<<-1<<endl; }
}
CODEZILLA question
https://www.codechef.com/COZI2017/problems/COZIA how this solution is get accepted??-https://www.codechef.com/viewsolution/13096241 May be the pair is exist between 1st and last element then this solution gives WA?