send_nodes's blog

By send_nodes, history, 6 years ago, In English

First, I really need to apologize for the round. There was a serious problem in D that was even covered in the sample test, that the main solution did not handle correctly. I should have been much more careful with this problem and looked for these kind of cases. Unfortunately, it was a big enough issue that caused the round to be unrated. I know this upset a lot of people, but it's tricky to find a solution to this kind of problem after the problem has happened.

I still hope the problems were good quality. If you learned something new from the round, or from this editorial, then the round was worth it. I would advise to solve the problems you couldn't solve during the contest, so you can take away something from the round.

If you want any further clarification on a problem, please ask in comments!

821A — Okabe and Future Gadget Laboratory

We can simulate exactly what's described in the statement: loop over all cells not equal to 1 and check if it doesn't break the city property. To check if a cell breaks the property, just loop over an element in the same row, and an element in the same column, and see if they can add to give the cell's number. The complexity is O(n4).

Sidenote: The definition of lab here was actually inspired from a USAMTS problem in 2016.


821B — Okabe and Banana Trees

The critical observation to make is that the optimal rectangle should always have a lower-left vertex at the origin. This is due to the fact that the line has positive y-intercept and negative slope: any rectangle which doesn't have a vertex at the origin could easily be extended to have a vertex at the origin and even more bananas.

Then, we just need to try every x-coordinate for the upper-right corner of the box and pick the maximum y-coordinate without going over the line. We can compute the sum of any rectangle in O(1) using arithmetic series sums, so this becomes O(bm) because the x-intercept can be up to bm. You can make it faster by trying every y-coordinate; this makes the complexity O(b), but this was unnecessary to solve the problem.

Can you solve the problem with better complexity?

O(b) Code

821C — Okabe and Boxes

It looks like Daru should only reorder the boxes when he has to (i.e. he gets a remove operation on a number which isn't at the top of the stack). The proof is simple: reordering when Daru has more boxes is always not worse than reordering when he has less boxes, because Daru can sort more boxes into the optimal arrangement. Therefore, our greedy algorithm is as follows: simulate all the steps until we need to reorder, and then we resort the stack in ascending order from top to bottom.

This has complexity O(n2 log n). However, we can speed this up if we note that whenever we reorder boxes, any box currently on the stack can be put in an optimal position and we can pretty much forget about it. So whenever we reorder, we can just clear the stack as well and continue. This gives us O(n) complexity because every element is added and removed exactly once.


821D — Okabe and City

First, let's make this problem into one on a graph. The important piece of information is the row and column we're on, so we'll create a node like this for every lit cell in the grid. Edges in the graph are 0 between 2 nodes if we can reach the other immediately, or 1 if we can light a row/column to get to it. Now it's a shortest path problem: we need to start from a given node, and with minimum distance, reach another node.

Only problem is, number of edges can be large, causing the algorithm to time out. There are a lot of options here to reduce number of transitions. The most elegant one I found is Benq's solution, which I'll describe here. From a given cell, you can visit any adjacent lit cells. In addition, you can visit any lit cell with difference in rows at most 2, and any lit cell with difference in columns at most 2. So from the cell (r,c), you can just loop over all those cells.

The only tricky part is asking whether the current lit row/column should be a part of our BFS state. Since we fill the entire row/col and can then visit anything on that row/col, it doesn't matter where we came from. This means that you can temporarily light each row/column at most once during the entire BFS search.

So complexity is O(n + m + k), with a log factor somewhere for map or priority queue. Interestingly enough, you can remove the priority queue log factor because the BFS is with weights 0 and 1 only, but it performs slower in practice.

You can see the code implementing this approach below.

Benq's code:

Another approach to this problem was using "virtual nodes". Virtual nodes are an easy way to put transitions between related states while keeping number of edges low. In this problem, we can travel to any lit cell if its row differs by <=2, or its column differs by at most 2, but naively adding edges would cause O(k^2) edges.

Instead, for every row, lets make a virtual node. For every lit cell in this row, put an edge between the lit cell and this virtual node with cost 1. We can do something similar for every column.

Now, it's easy to see that the shortest path in this graph suffices. A minor detail is that we should divide the answer by 2 since every skipping of a row or column ends up costing 2 units of cost.

821E — Okabe and El Psy Kongroo

You can get a naive DP solution by computing f(x, y), the number of ways to reach the point (x, y). It's just f(x - 1, y + 1) + f(x - 1, y) + f(x - 1, y - 1), being careful about staying above x axis and under or on any segments.

To speed it up, note that the transitions are independent of x. This is screaming matrix multiplication! First, if you don't know the matrix exponentiation technique for speeding up DP, you should learn it from here.

Now, let's think of the matrix representation. Since the x dimension is the long one and the y dimension is small, lets store a vector of values dp where dpi is the number of ways to get to a y value of i at the current x value. This will be the initial vector for matrix multiplication.

Now, what about the transition matrix? Since our initial vector has length y and we need a matrix to multiply it with to map it to another vector with length y, we need a y by y matrix. Now, if you think about how matrix multiplication works, you come up with an idea like this: put a 1 in the entry (i,j) if from a y value of i we can reach a y value of j (i.e. |i - j| ≤ 1). Don't believe me, multiply some vector times a matrix of this form to see how and why the transition works.

You can then build this matrix quickly and then matrix exponentiate for under every segment and multiply by the initial vector, then make the result as the new initial vector for the next segment. You should make sure to remove values from the vector if the next segment is lower, or add values to the vector if the next segment is higher. This gives complexity O(nh3 log w) where h = 16 and w = k.


Full text and comments »

  • Vote: I like it
  • +127
  • Vote: I do not like it

By send_nodes, history, 6 years ago, In English

Hi everyone!

It's the round you've been waiting for... Codeforces Round #420 (Div 2). It will take place tomorrow, 25 June 2017, at 17:35 MSK. As always, Div. 1 participants are encouraged to join out of competition. The round will be rated for Div. 2 participants and will have 5 problems to be completed in 2 hours.

I wouldn't be able to create this round without the help of many people: KAN for lots of help in preparing the contest, 300iq and Alladdin for testing and providing feedback, and as always MikeMirzayanov for the Codeforces and Polygon platforms.

This will be my second contest, and I'm glad to get such a nice round number :). Hopefully, you'll find the problems interesting. Of course, you should read all the problems so you can solve problems you find easy or interesting.

To excite some and disappoint others, the round theme will have nothing to do with the number 420. Instead, continuing the anime themes of the last two rounds, round #420 will feature mad scientist Rintaro Okabe (don't read spoilers!) from the anime Steins;Gate. Statements will not contain any spoilers, but you might find the problems slightly more amusing if you've watched the series. Of course, you should watch the series if you havent :)!

As per Codeforces tradition, scoring distribution will be announced shortly before the contest. Good luck, and I hope you can help Okabe with all 5 tasks :D!

Scoring is standard: 500-1000-1500-2000-2500!

Update: Sorry for delays.

Update: Editorial is here:

I really apologize for the issues during the round. It's upset a lot of people and I should have taken more care. Hopefully you won't hold this against Okabe or Steins;Gate anime :P

Here are the contest winners! Congratulations!

Div. 1

  1. nuip
  2. uwi
  3. sugim48
  4. xumingkuan
  5. HellKitsune

Div. 2

  1. Parachutes
  2. forgive_her
  3. visitWorld
  4. y553546436
  5. a_student_follower

Thanks for participation everyone! Hope to write more problems in the future (without bugs)!

Full text and comments »

  • Vote: I like it
  • +104
  • Vote: I do not like it

By send_nodes, history, 6 years ago, In English

Hi community,

I've been thinking about some problem for a while, and was wondering if it has a polynomial time solution. The problem goes as follows:

You character starts with B blue tickets and R red tickets. There are N offers proposed to you, the i'th in which you first lose ai blue tickets, bi red tickets, and then right afterwards gain ci blue tickets and di red tickets (Suppose all values except N are  ≤ 109). You lose if you ever have a negative amount of either ticket type. Is it possible to complete all offers and not lose?

Obviously you first want to complete all offers that yield positive profit for both red and blue tickets, but even then there might be some offers you can't complete. The rest is not so trivial.

Does anyone have ideas or seen this problem before? As said, this is original, so I don't have a problem link and am simply looking for the best time complexity possible.

Full text and comments »

  • Vote: I like it
  • +16
  • Vote: I do not like it

By send_nodes, history, 7 years ago, In English

Hi everyone, here are the solutions to the contest problems.

712A — Memory and Crow

Note that a[i] + a[i + 1] = b[i]. Use the initial condition b[n] = a[n] and we can figure out the entire array b.

Time Complexity: O(n)


712B — Memory and Trident

First, if S has odd length, there is no possible string because letters must come in opposite pairs. Now, let's denote the ending coordinate after following S as (x, y). Since S has even length, |x| has the same parity as |y|. Suppose they are both even. Then clearly, we can make x = 0 in exactly moves, and same for y. If instead they are both odd, then we can change exactly one x-character into a y-character. With the correct choices of these characters, now our string has |x| and |y| with even parity, thus reducing to the problem above. Therefore, the answer is (|x| + |y|) / 2.

Time Complexity: O(|S|)


712C — Memory and De-Evolution

Let's reverse the process: start with an equilateral triangle with side length y, and lets get to an equilateral triangle with side length x. In each step, we can act greedily while obeying the triangle inequality. This will give us our desired answer.

Time Complexity: O(log x)


712D — Memory and Scores

One approach to this problem is by first implementing naive DP in O((kt)2). The state for this is (diff, turn), and transitions for (diff, turn) is the sum (diff - 2k, turn - 1) + 2(diff - 2k + 1, turn - 1) + 3(diff - 2k + 2, turn - 1) + ... + (2k + 1)(diff, turn - 1) + 2k(diff + 1, turn - 1) + ...  + diff( + 2k, turn - 1).

Now, if we use prefix sums of all differences in (turn-1), along with a sliding window technique across the differences, we can cut a factor of k, to achieve desired complexity O(kt2).

However, there is a much nicer solution in O(kt log kt) using generating functions(thanks to minimario). We can compute the coefficients of , and the coefficient to xi corresponds to the number of ways we can form the difference i. To compute these coefficients, we can use the binomial theorem.

Time Complexity: O(kt2)


Time Complexity: O(kt log kt)


712E — Memory and Casinos

Lets think about two segments of casinos [i, j] and [j + 1, n]. Let L([a, b]) denote the probability we dominate on [a, b], and let R([a, b]) denote the probability we start on b and end by moving right of b. Let

l1 = L([i, j]),

l2 = L([j + 1, n]),

r1 = R([i, j]),

r2 = R([j + 1, n]).

You can use a geometric series to figure out both L([i, n]) and R([i, n]) using only l1,l2,r1, and r2. To derive these series, think about the probability we cross over from j to j + 1 once, twice, three times, and so on. The actual formulas are,

Now we can build a segment tree on the casinos, and use the above to merge segments.

Time Complexity: O(N + QlogN)


Full text and comments »

  • Vote: I like it
  • +46
  • Vote: I do not like it

By send_nodes, history, 7 years ago, In English

Hi everyone. I'm trashfirstsearch, and I used to be blue...

Anyways, Codeforces Round #370 (Div. 2) will take place on 10 September 2016 at 19:35 MSK. As usual, Div.1 participants can join out of competition.

Much thanks to GlebsHP for helping me with preparing the contest, MikeMirzayanov for the Codeforces and Polygon platforms, and minimario and Wrong_Answer_Exceeded for testing problems.

This will be my first contest prepared on Codeforces, and I have prepared all the problems with the intent of making them interesting for everyone. It is, as usual, strongly advised to read all the problems.

Good luck, and I hope you will gain rating(and force someone else to lose it >:) ).

Update: Congratulations to the winners:


  1. KrK

  2. halyavin

  3. fhlasek

  4. vintage_Vlad_Makeev

  5. Kmcode


  1. __0v0__

  2. palayutm

  3. Strikeskids

  4. khanh.tang

  5. pkq2010

Here is the editorial.

I sincerely apologize for the problems during the contest. However, I hope everyone found the problems interesting! Thanks to everyone who participated and helped with the problems!

Full text and comments »

  • Vote: I like it
  • +264
  • Vote: I do not like it

By send_nodes, history, 8 years ago, In English

I've been having a problem with 2-D arrays for a while. If I allocate a 2-D array with dimensions 1000x1000, then when I debug, the program crashes. For example, this code is crashing:

#include <queue>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <complex>
#include <fstream>
#include <cstring>
#include <string>

using namespace std;

typedef long long ll;
typedef complex<double> point;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector< vector<int> > vvi;

#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 99999999
#define MOD 1000000007
#define MAX 100000
#define ITERS 10000
#define pi 3.1415926

int main(){
	int n,m;
	cin >> n >> m;
	int arr[1000][1000];
			int nxt;
			cin >> nxt;
			arr[i][j] = nxt;
	int dpa[1000][1000];
	int dpb[1000][1000];

I'm using MinGW GCC g++ 4.8.1. Any ideas on what the issue is? When I run, I get an error message saying:

".exe has stopped working. Windows is checking for a solution to the problem..."

Full text and comments »

  • Vote: I like it
  • 0
  • Vote: I do not like it

By send_nodes, history, 8 years ago, In English

I'm curious to know what all of you keep in your coding library to make your coding faster. I'm keeping a geometry library storing basic computational geometry tools(dot, cross, intersect, distance to line, centroid, area, etc.) and a graph theory library having max flow and flood fill.

I ask because I want to know how much is necessary to perform well in contests.

Full text and comments »

  • Vote: I like it
  • -9
  • Vote: I do not like it

By send_nodes, history, 8 years ago, In English

Hi, I was having some trouble on figuring out the solution to this

It's obviously some sort of DP, and by looking at some code, I can tell that they are using left and right pointers, but I am unable to grasp the overall solution. Could someone please let me know the solution :D

Full text and comments »

  • Vote: I like it
  • 0
  • Vote: I do not like it

By send_nodes, history, 8 years ago, In English

I've seen "offline solution" a lot on codeforces. What does it mean? Is it a solution that precomputes answers?

Full text and comments »

  • Vote: I like it
  • +14
  • Vote: I do not like it

By send_nodes, history, 8 years ago, In English

I was working on this problem:

I spent a fair bit of time on it, and I knew while solving it that it was a topological sorting problem. However, I have gone through the USACO training pages to learn my algorithms, which doesn't have a section on topological sorting. I know standard graph algorithms like bfs,dfs,warshall,dijkstra, etc. but I don't know how to solve these topological sorting problems. The editorial mentions that this is a classic topological sort problem.

My question is, how can dfs be applied to solve this problem, and where can I find more theory/practice problems to practice topological sorting.


Full text and comments »

  • Vote: I like it
  • -3
  • Vote: I do not like it