### awoo's blog

By awoo, history, 6 months ago, translation, 1841A - Game with Board

Idea: BledDest

Tutorial
Solution (BledDest)

1841B - Keep it Beautiful

Idea: BledDest

Tutorial
Solution (awoo)

1841C - Ranom Numbers

Idea: BledDest

Tutorial
Solution 1 (Neon)
Solution 2 (BledDest)

1841D - Pairs of Segments

Idea: BledDest

Tutorial
Solution (BledDest)

1841E - Fill the Matrix

Idea: BledDest

Tutorial
Solution (awoo)

1841F - Monocarp and a Strategic Game

Idea: TheWayISteppedOutTheCar and BledDest

Tutorial
Solution (TheWayISteppedOutTheCar)  Comments (86)
 » 6 months ago, # | ← Rev. 2 →   I am facing time-limit-exceeded in test-case3 Problem B solution
•  » » Remove the line // s = s + "1" from your code because adding "1" instead of '1' works as string concatenation and its time complexity is O(n^2) thus making your code's overall complexity as O(n^3) for large n.
•  » » » Yeah, it works. Thanks!
•  » » » 6 months ago, # ^ | ← Rev. 2 →   I made a test to find that it has nothing to do with whether you use "1"(string) or '1'(character).I wrote such code below:（my compilation standard is G++17) #include #include int main() { std::string s; for (int i = 1; i <= 1e6; ++i) s += 'c'; for (int i = 1; i <= 1e6; ++i) { // s += "c"; // s += 'c'; // s = s + "c"; // s = s + 'c'; } std::cout << s << '\n'; } If I run the first two annotations I wrote(which means removing // in front of s += "c" or s += 'c'), it would complete and output immediately. Instead, if I run the last two annotations I wrote(which means removing // infront of s = s + "c" or s = s + 'c', the program ran for a long time without outputing.So the key is that you can't use operator = but you must use operator +=. The former is $O(|s|)$ for there is a copy occurs, while the latter is $O(1)$(in average) for it would just append a character/string(with a constant length) to the end of $s$.
•  » » » » According to the C++ standard, only s.push_back('c'); is guaranteed to have amortized constant time complexity. In practice s += 'c'; will behave the same, since there is no practical benefit to making it any slower. So the key is that you can't use operator = but you must use operator +=. Using += is good advice, but the reason that a copy is made isn't because of the use of = for assignment, but rather because s is an lvalue in the expression s + 'c'. You can make the assignment equally efficient with: s = std::move(s) + 'c'; Of course, it's much easier to just write s += 'c' at this point.
 » 6 months ago, # | ← Rev. 2 →   I have made a detailed video (its in hindi language) to solve problem C using 3 different approaches. Video link : link Let me know if it helps you :)
 » 6 months ago, # | ← Rev. 5 →   I'm going to share some of my solutions since they are not mentioned in the editorial.For 1841C - Ranom Numbers, I basically did some sort of brute force, checking every possible replacement for a character and taking the maximum. The trick is that when you decrease a character, some of the characters that are directly affected by you may not be affected anymore (or may be affected by some other letter on the right of the current letter), and when you increase a character, some of the characters are before you and not affected by anybody may be affected by you.To check this, I made a vector called where where where[i] are the indices where character i occurs, so that when checking whether there is a greater or smaller character after some index it becomes easy with a std::lower_bound (or binary search). Moreover, I maintain a frequency of all non-affected characters before me and all characters that are directly affected by me, and then do some calculations. (I admit it, the solution is hairy) Code hereFor 1841D - Pairs of Segments, I sorted according to the left boundary (and so let [l[i], r[i]] denote the intervals after sorting). Now, use Dynamic Programming where dp[i] is the minimum number of removed intervals starting at i, and the transitions are either dp[i] = dp[i + 1] + 1 where we just remove the current interval or we try to see if we can merge it, so we loop over all segments with index j > i to find the segment that intersects with i with minimum right boundary, let this interval be x (if not found, just don't proceed with this transition), and let R = max(r[x], r[i]) (basically the right boundary after merging)and then we basically try to minimize with dp[j] + removed where j is such that j > i and l[j] > R and removed denotes all segments k where i < k < j and k is not x, which are all the removed segments. Code hereFor 1841E - Fill the Matrix, I used the same general idea: we just collect all contiguous segments in the same row in the matrix by considering from the bottom row to the top row and noting that some of the black towers split some segments in two.However, I feel my implementation was a bit simpler, it was using an idea called deltaing that I learned from Algorithms Live's amazing episode 9: "Solution Bags". The idea is to maintain A vector called where where where[i] are the indices where the number i in the array. A set (called st cause I didn't think what to call it) containing all the indices of the black cells in the current row. It initially contains -1 and n (since indices are zero-based) A vector segments where segments[i] denotes the frequency of all segments of size i, initially all zeros except for segments[n] = n, this is to denote that for all we know, all segments didn't occur, and a segment of size n occurs n times (as if the table is empty), and we will update this as we go (this is the "deltaing" part) Now, we loop on row j from n down to 1, and we note that there are black cells in where[j] that split the segments. How do we know which segments are being split? Using the set st: -Suppose that a black cell appears at index i, we can find the previous black cell as L = *prev(st.lower_bound(i)) and the next black cell as simply R = *st.lower_bound(i), and we know they both exist since we started with -1 and n in the set. The update goes as follows: The segment with length R - L - 1 will be removed, meaning that it will not exist for j rows from now on, so we decrement segments[R - L - 1] -= j, meaning that for all we know, we assumed it exists for all segments[R - L - 1] rows but now we know that it will not exist for j rows (from now on). A segment with length R - i - 1 will exist now, so we increment segments[R - i - 1] += j, meaning that for all we know, unless we update it, a segment of length R - i - 1 will exist for j more rows. A segment with length i - L - 1 will similarly exist now, so segments[i - L - 1] += j, for the same exact reason. We insert i in the set st. After we're done we basically have the frequency of each size of a segment, and we can just loop greedily from the largest segment to the smallest segment and fill as much as we can with our m integers. Code here.
•  » » I did same in C 209455681 but different imp
•  » » I tried the similar approach in which for every index I checked how the initial sum is affected if I changed the particular index. But for reducing time I precomputed the initial sum, frequency of character before the particular index, and after the index and tried to make changes on that so if I had changed that to particular character then how it might affect the initial sum. But I was not able to get it right :( 209557678
•  » » 6 months ago, # ^ | ← Rev. 3 →   In D soln , In last paragraph shouldn't it be and then we basically try to minimize , instead of maximize
•  » » » Fixed it, thanks.
•  » » Your explaination for 1841D is brief and awesome. Could you reason about why you are pairing the i'th segment with the segment whose right boundary is minimum (In case we are not removing the i'th pair) ?
•  » » » 6 months ago, # ^ | ← Rev. 2 →   It's because whatever segment x you choose to pair with, you'd have to go minimize with all dp[j] where l[j] > R and noting that R = max(r[x], r[i]), so whenever you minimize this R, you get more options of j to pair with, so we just choose the one with the minimum r[x].
 » I am getting TLE on test case 3 in Problem B 209457885. can someone tell the reason?
•  » » Your complexity is too high man, your code is O(n^2) but it should be O(n) , you should not check if it "is_beautiful" for every addition.check what i have tried:https://codeforces.com/contest/1841/submission/209460248 : similar to what have you done and it exceeds the time limit of course.https://codeforces.com/contest/1841/submission/209466517 : (ignore check function) this is the solution in O(n)
 » 209599406 I'm facing runtime error for this solution but it works locally for me
•  » » Compiling with debug flag -D_GLIBCXX_DEBUG gives "Error: attempt to subscript container with out-of-bounds index -1". This is happening on the line return dp[id][k][mx]=res;, since mx can be equal to -1.
•  » » » Oh, thanks! changed it to 0 and now it works. kinda weird how it didn't throw any error on my ide
 » F can be solved in higher dimensions $d$ in $O(n^{d-1}(d + \log n))$: https://link.springer.com/article/10.1134/S1990478917040160
 » There is O(NlogN) solution for D, we can sort segments by right border, then calculate dp = answer for prefix, if we using i-th segment in pair, we can greedily use intersecting segment with the maximum left border (we can find it with segment tree), we can do this because it increases left border of their union. here is the code 209602279
•  » » I don't like DPClick only if you like clean codes.The $x$ variable checks where we have left the i-th pair(that is formed) and the $y$ variable checks what's the new r in [l, r] in the j-th pair (that is going to form. Obviously i < j ) My Submission : 209491152
•  » » » By the way, you don't need to sort by the left endpoint: 209680351
•  » » » » Nice Solution!!!
 » Any body facing failing testcase issue in Problem C Try this testcase: Input: 1 DDDDDDDDDDDDDDDDDDDDDDDDE  Output: 25000 Explanation: Replace 'E' with 'D', if we replace 'D' with 'E' we will be left with two 'E' and remaining 'D' and the result will be 2*10000-23*1000 = -3000, if we replace 'E' with 'D' now we don't have any 'E' and all the 'D' will be positive that is 25*1000 = 25000.
 » For F, what does it mean to calculate the Minkowski sum of a single set of points? I’m familiar with Minkowski sum of two sets / convex polygons. However, Minkowski sum of the set of all vertices with itself only gives pairwise sums. It looks like here we are interested in sums of all subsets though, which looks harder.
•  » » 6 months ago, # ^ | ← Rev. 5 →   For each group add (0, 0) and (a - b, c - d) to the Minkowski sum to give the option of taking or not taking.
•  » » » Ah that’s clever, thanks! I misinterpreted the editorial to mean “sum of {(0,0), (x1,y1), (x2,y2), …}” instead of “sum of all {(0,0), (x,y)} pairs”
•  » » » » Sorry to bother you, but can you explain how the code in the solution computes the Minkowski sum? I only know how to calculate the Minkowski sum of two convex hulls:)
•  » » » » » I compute the Minkowski sum with D&C.209634929
•  » » » » » 6 months ago, # ^ | ← Rev. 2 →   The difference array of the minkowski sum of two convex polygon starting from the bottomost leftmost point going counterclockwise is equivalent to the sorted concatenation of the difference arrays sorted by counterclockwise order starting from the negative y axis ((0, -1) would be last).of those two convex polygons, so you can just maintain the differences and the bottommost point after adding every pair of points. ie. (0, 0), (1, 0), (0, 1) has a difference array of (1, 0), (-1, 1), (0, -1)(0, 0), (1, 1) has a difference array of (1, 1), (-1, -1)Their minkowski sum is (0, 0), (1, 0), (2, 1), (1, 2), (0, 1) which has a difference array of (1, 0), (1, 1), (-1, 1), (-1, -1), (0, -1)Since for each pair of points being added to the polygon there is only (0, 0) and (a - b, c - d), you can just add (a - b, c - d) and (b - a, d - c) to the difference array and sort them all by counterclockwise order afterwards. You just have to maintain the current bottommost leftmost point which is (sx, sy) as well.
•  » » » » » » I got it! Thank you very much.
 » It would be better if you provide the solution of B in c++
 » Another way to do problem E is with a stack in O(n). Because you are essentially given a histogram, we can use a stack to maintain the heights of the rectangles and length of the rectangles, while trying to maximize the length of the rectangle. Then whenever we pop from the stack we add to a count of a specific size of a segment.More details are in this submission: 209610350
 » 6 months ago, # | ← Rev. 2 →   For Problem E, I maintained the empty spaces in each column .. then solving for some range from {l,r} find the minimum empty space in that range .. and add {(r-l+1), minV} to a set, subtract minV from all elements in the range {l,r} as that much space is utilized now, then we can then solve it recursively for range {l, minIdx-1} and {minIdx + 1, r}.Video Solution — https://www.youtube.com/watch?v=N0_QB3hPP_8
 » Simple approach for D with complexity o(n*log).
•  » » 4 months ago, # ^ | ← Rev. 2 →   Maintaining the set is also not required just a variable is enough that stores the right end of the segment which does not intersect with the previous pair. SolutionI just wanted to mention this, I know you would already know this.
•  » » » That is true, thank you for your mention.
 » In problem D, is there a graph based solution where we the graph has edges between intersecting intervals?
•  » » I tried to think of this but I am stuck In the graph solution I think you have to find the maximum k such that there exists k edges which are disjoint and donot have edges between them but I am not able to find out which property of graphs can be exploited further to arrive at the solution.
•  » » » This is binary-searchable
•  » » » » I am sorry but I didn't uderstand what you meant by binary searchable ??
•  » » » » » If you can make 4 pairs then you can make 3 pairs of course. What remains is the check function though which is hard to find
 » In problem C, it states that $dp_{i,j,k}$ is the maximum value of the number if we considered $i$ first characters, applied $k$ changes to them ($k$ is either 0 or 1), and the maximum character we encountered so far was $j$ ($j$ can have 5 possible values). But why we only need size of 2 for $i$ in int dp; here?
•  » » when calculating the value of dp [i][][], just the value of dp[i — 1][][] is needed. Therefor you only need dp [][], where dp [][] is dp[i — 1] and dp[][] is dp [i][][] .Remember to swap them after each for loop
 » 6 months ago, # | ← Rev. 3 →   can anybody please find what is an error in my code for problem D it gives WA in test case 5for _ in range(int(input())): n = int(input()) p = [] for i in range(n): u,v = map(int,input().split()) p.append((u,v)) p.sort() st = [] en = [] for i in p: st.append(i) en.append(i) dp = [0 for i in range(n+1)] for i in range(n-1,-1,-1): u = bisect(st,en[i]) for j in range(i+1,u): p1 = bisect(st,en[j]) dp[i] = max(dp[p1] + 2,dp[i+1],dp[i]) dp[i] = max(dp[i],dp[i+1]) print(n-dp) Your text to link here...
•  » » Take a look at Ticket 16891 from CF Stress for a counter example.
•  » » » thanks
 » my very easy to understand dp solution for problem c: #209771203
 » I have a different and quite interesting approach for problem C.Wanted to use $1-n$ loops so $s$ = " " + $s$First, if we modify the $i-th$ character of string $s$, the result when calculating all characters of $s$ to the right of $i$ does not change. Therefore it can be precalculated (for briefness, I assume we store these in an array called $sfsum$). $(1)$We can also precalculate the max character of every suffix of string s in an array (for briefness, I call it $sfmax$). In calculation, the $i-th$ character will have a negative sign if $i$ < $sfmax[i + 1]$ ($sfmax[n + 1]$ = $0$), otherwise it will have a positive sign. $(2)$Let $cnt$ be an array such that $cnt[c][i]$ is the number of times (char)($c$ + 'A') appears in $s.substr(1, i)$. Defining the "practical" value of character $c$ in string $s$: Consider the calculating process of $s$; for every negative sign of c, -1 from that value and for every positive sign we add 1. Let $value$ be an array such that $value[c][i]$ is the "practical" value of (char)($c$ + 'A') in $s.substr(1, i)$. $(c: 0-4)$ $(3)$From (3) we can see that the ranom value of string $s$ of length $x$ (using its $value$ array) is $value[x] + value[x]*10 + value[x]*1e2 + value[x]*1e3 + value[x]*1e4$. $(4)$$(1)(2)(3)(4)$ Let $ans$ be the answer. For every $i-th$ character of $s$, we can quickly calculate the ranom value of the new string if we modify it:Let $c: 0-4$ be the new value of that character, then let $tmp$ be the new ranom value.If $(c >= sfmax[i + 1])$, $tmp$ = 10^$c$; else $tmp$ = -(10^$c$). $tmp$ += $sfsum[i + 1]$ (not affected part)For $ch: 0-4$ (considering every character $'A' - 'E'$) If ($ch >= c$ and $ch >= sfmax[i + 1]$) $tmp$ += $value[ch][i - 1]$ (this character is >= every character to $s[i]$'s right so its practical value for $s$ = its practical value for $s.substr(1, i)$) Else $tmp$ -= $cnt[ch][i - 1]$ (there is a larger character than this to the right of $s[i]$ in $s$) Then we just update $ans = max(ans, tmp)$Implementation: My CodePls tell me if im wrong :D
•  » » Edit: How to precalculate $value$:For every $c: 0 - 4$:For $i: 1 - n$: If ($s[i] - 'A' == c$) $value[c][i] = value[c][i - 1] + 1$ ($s[i]$ is last character of current substring so +1) If ($s[i] - 'A' > c$) $value[c][i] = -cnt[c][i]$ (last character of current substring >= $c$ so every time $c$ appears, $value[c][i]$--) Else $value[c][i] = value[c][i - 1]$ (nothing happened)
 » Hi!I did not understand the approach of problem B on the editorial. I solved it though 209826444 . Can anyone help me understand this approach please.Thanks for your time
 » I can't come up with a test on which the solution of problem B breaks, help please: 209842593
•  » » Take a look at Ticket 16896 from CF Stress for a counter example.
•  » » » I found a bug yesterday, thanks for your attention) I've never heard of such a site, I'll have to look...
 » The gap between B and C are too big, make the round speedforces for people < expert.
 » In problem C, my solution is segment tree, but there isn't data structures tag, Can anyone add it ? this is my solution : 209477665
 » The time limit of 1 second is too tight for problem F, at least for Java language. Math.atan2(y,x) is convenient to get the angle of (x,y) in polar coordinate yet it is too expensive to be used for n = 300000 test case. BigInteger is convenient to represent the square sum precisely yet it is too expensive to be used for n = 300000 test case, so double is used instead. Precompute y/x ratio for points in each quadrant is necessary to sort them in angle order (compute each ratio long(n) times lead to TLE). The tight limit also forbit other variants of solutions that are essentially the same idea and complexity. The main risk to have a very tight time limit is it rejects otherwise reasonable solutions that deviates from the tutorial one in some perspective, or code that are otherwise more intuitive and readable, which are important in software development.
 » 6 months ago, # | ← Rev. 2 →   D can be solved in O(nlog) using rmq sort segment by right border keep the maximum left border of range [i, i + 2^j) in an array update dp (dp[i] means minimum answer with fixing i-th segment) code
 » 6 months ago, # | ← Rev. 2 →   There is O(nlogn) solution for 1841D - Pairs of Segments, without using any RMQ or DP.Basically just sort the segments by right end increasing order, and then left end decreasing.Now iterate over these segments, and keep track of two end points. First is the end point of rightmost segment, that is not intersecting with any other ( one_end in my code). Second is the end point of rightmost intersecting segment ( r_end in my code).Whenever any segment's left end is intersecting the r_end, we can discard it. Or, if we find a segment that is not intersecting even with one_end, then we can update one_end and discard this segment, as we only allow pairs of intersecting segments.After exiting loop, if one_end remains, then add that segment also to discarded.Just print no. of discarded segments.My solution -> 210253422
 » I am unable to understand solution of D. Why do we need to sort the vector of unions based on second element of pair?? Can't we do it by general method of sorting.
•  » » Greedy: Taking the current segment if it doesn't intersect with the last segment which we picked.When the segments are sorted by their endpoints, we can be sure that this greedy will work, because as we traverse through the array of segments (from left to right), we can say that leaving the current segment and picking any subsequent one will never be better. (Why? because the endpoint of any subsequent segment will be greater than the current segment, and hence it would possibly intersect with more segments than the current segment). Thus every time we encounter a segment that doesn't intersect with the last picked one, we can simply select it and get the correct answer. Now, to answer your question: You can sort the points by the general method (by their starting points) as well, but then, you would have to traverse the array from right to left, (Why? reason similar to the above explanation). This works. Accepted Submission
 » Hello,My submission for problem F is having trouble with test case 40. Can anyone offer some insight into what the issue may be?Participant's output 170138151766204922271336838014697570689Jury's answer 1601570Thanks very much
•  » » Take a look at Ticket 16900 from CF Stress for a counter example.
•  » » » Thanks for the reply. I tried the test case from the link provided above, but my program correctly outputs the expected output (2) when I run it locally, despite what the program's output is on ticket.I'm not familiar with errors relating to large integers... perhaps there is some printing error?
 » I writed N * logN solution for problem 1841D instead of N^2 * logN :)
 » Without knowing about Minkowski sums, F can be solved using a sliding (or rotating) window:One can show that the optimal vector sum has positive dot product to all its terms, and negative dot product to every vector not in the sum. Thus the optimal sum induces a half-space on the plane from which the component vectors can be recovered. Then the problem reduces to finding this half-space, or at least the vectors that lie inside it. This can be accomplished (after sorting vectors by angle) by sweeping out the plane.
•  » » Thanks so much for the code! Finally succeeded after debugging for 2 days. Some more information for others wanting to write the sliding window solution: There's one tricky edge case when expanding the window to cover half of the plane. If the code is written by expanding the window [i, j) by comparing if j is 180 degree from i we might accidentally pick up vectors with same direction as i. But when we increase i, those vectors will not be in the same half plane as the new i. int ptr = 0; lll x = 0, y = 0, mx = 0; for(int i = 0; i < n; i++) { while(ptr < i + n) { lll cp = cross(A[i % n], A[i % n], A[ptr % n], A[ptr % n]); lll dp = dot(A[i % n], A[i % n], A[ptr % n], A[ptr % n]); if(cp < 0 || (cp == 0 && dp < 0)) { break; } // remember to add this condition to not loop back if((cp == 0) && (dp > 0) && ((ptr % n) < i)) { break; } x += A[ptr % n]; y += A[ptr % n]; ptr++; mx = max(mx, x * x + y * y); } x -= A[i]; y -= A[i]; mx = max(mx, x * x + y * y); } 
•  » » »
 » Can anyone help check out what's wrong with my submission to problem D? It feels like a quite straightforward problem, but I'm unable to find what's wrong... https://codeforces.com/contest/1841/submission/210784413
•  » » Take a look at Ticket 16903 from CF Stress for a counter example.
 » Can anyone tell what's wrong with this submission — https://codeforces.com/contest/1841/submission/211982826I have use simple dp approach where dp[I][j] is the answer when ith char is replaced with j..
•  » » Take a look at Ticket 16992 from CF Stress for a counter example.
 » Problem D can be solve with O(nlogn) time. Solution
•  » » Solution A much easier implementation using O(nlogn) Time and O(1) Auxiliary space
 » Problem D — Pair of Segment: Nlog(N) solution.concise and straightforward solution using Segment Tree, UpperBound on a sorted array, and Dynamic Programming. Used segment tree to find the minimum element in a range and the central concept is only based on 1D dynamic programming.Problem D solutionthe concept involves only 2 states you delete the current element and save the answer as dp[i+1] + 1 or, keep the current element, and then choose the most optimal intersecting element, and delete the rest the state will be j-i-2 + dp[j], where j is the index of closest element not intersecting both the current element, and the chosen optimal element, which will pair with the current element. Note: the chosen optimal element will be the intersecting element with the least [Ri]. cause this provides the least chance of it intersecting other elements.
 » I adapted the sample solution for F and replaced the __int128 and pairs of ll with (long) double. However, now i always get TLE in test case 18.Here is my code: https://codeforces.com/contest/1841/submission/217939111The original solution (which gets accepted perfectly fine) is this: https://codeforces.com/contest/1841/submission/217939364The problem is the sorting step. But it should be possible to solve this task with floating point values, right?So does anyone have an idea?
•  » » This submission here works perfectly fine: https://codeforces.com/contest/1841/submission/217941363This new solution does not use cmp_ang() for sorting, but cmp_ang2(). The Problem is really the call to arg() (which also just calls atan2()). I replaced it with another ... more complex way of comparing the angles and afterwards rotating it (probably the rotation can be eliminated with a slight variation as compare function).However what remains to be answered is: why is atan2 so slow???
 » In question D I think I have also done something similar but my solution: https://codeforces.com/contest/1841/submission/218822785 is showing wrong answer on test 5.... could someone point out the faulty logic? I am basically sorting all given pairs in ascending order and then checking each element to see if a union can be taken with the next one... if so I am considering that pair and since its sorted vector I'm indirectly also making sure that the same pair doesn't get included in more than at max 1 pair of pairs by setting the current check (l) to max of upper limits of a chosen pair.
•  » » Take a look at Ticket 17055 from CF Stress for a counter example.
 » Someone please tell me what is wrong in my code for problem C — codeI have written my approach inside the code. And my code should be easily understandable. I am stuck on this problem till now. It would be great if anyone of you could help me debug it.
•  » » Nevermind, found the mistake.
 » i have the [problem:1841D] i have the O(n log n) solution : 226512501
 » for problem 1841D - Pairs of Segments your complexity is too long time man, i have the O(n log n) solution : 226512501
 » Problem D should be O(nlogn) using dp, right? code