FairyWinx's blog

By FairyWinx, 12 months ago, translation, In English

Recently, the following problem was presented at the school BSUIR OPEN XIII:

Given an array of integers and point update queries. After each such query, you need to respond online: how many pairs $$$i, j$$$ exist that yield the maximum possible sum and are at a distance of no more than $$$k$$$.

Without online processing — this is almost a classic problem from the Canadian Olympiad for school students (solvable using DCP-offline), but we will learn to do it online. Essentially, I want to learn how to create a data structure that can account for each such pair exactly once. Personally, I can do it in $$$O(\log n)$$$ per query.

Let's complete the segment tree to a power of two (otherwise it won't work). Then we will have some number of levels, and at each level, we will have the same number of nodes. For convenience, let $$$l_v, r_v$$$ denote the segment that the subtree is responsible for, and let $$$lvl_{i, j}$$$ denote the node at level $$$i$$$ with number $$$j$$$ (the nodes at the same level are ordered by the increasing right boundary). We will also calculate $$$nxt_v$$$ — the last node at the level of node $$$v$$$ for which $$$r_{nxt} - r_v \leq k$$$ (in other words, this is the farthest node at the level for which any pair from these subtrees forms a suitable pair).

Then the statement is that it is sufficient to consider all pairs in the following subtrees:

For each node $$$v$$$, we say that the answer for it is the maximum of the answers from the left/right subtree, and also consider the optimum in pairs of subtrees $$$v, nxt_v$$$, as well as $$$v, 'nxt_v$$$, where $$$ 'nxt_v$$$ is the first node to the left at the level of $$$nxt_v$$$. We also take two optimums for the subtree of size $$$\leq k$$$.

Now, how to account for each pair exactly once — we will not merge two nodes if their ancestors also fit (that is, the maximum distance between pairs of nodes will be less than or equal to $$$k$$$). This fact is already obvious.

Proof: it passes stress tests, which means it is correct. Since the sizes of all trees are powers of two, and the condition is the same everywhere, this recount will only occur at one level (when we consider that if the ancestors fit, we do not account for this pair). In this case, at most $$$3$$$ nodes at this level will be involved. (Otherwise, their ancestors would also be relevant). In this case, this algorithm will indeed account for each pair exactly once, as these will be all relevant pairs. The uniqueness is obvious, so I will leave it for the reader to prove.

We have learned to account for each pair exactly once. Now we need to learn how to update with point changes. Let's note that when changing a node, the answer will only change for its ancestors, which is trivial to do, as well as for the nodes for which our node was one of the two right ones. We can easily precompute these nodes. Therefore, we need to recount the answer for them and then recursively update their parents. Given that we also need to update the parents, it results in $$$O(\log^2)$$$ (and it is quite long, as the recounting code itself is quite heavy). (Alternatively, if we carefully look at the proof, not many interesting nodes of the segment tree will change, resulting in $$$O(\log)$$$, but below is an implementation that runs in $$$O(\log^2)$$$).

Implementation

Full text and comments »

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

By FairyWinx, history, 12 months ago, translation, In English
Div2A
Div2B
Div1A
Div1B
Div1C
Div1D
Div1E
Div1F

Full text and comments »

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

By FairyWinx, 2 years ago, translation, In English

Problem A.

Solution

Problem B.

Solution

Problem C.

Solution

Problem D.

Solution

Problem E.

Solution

Problem F.

Soloution

Full text and comments »

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

By FairyWinx, 2 years ago, translation, In English

Neko Nya, Кодефорсес =^● ⋏ ●^=

I'm happy to invite you to participate in Codeforces Round 926 (Div. 2). It will take place on Feb/15/2024 17:35 (Moscow time) and in it, you will help a boy named Sasha win over a girl's heart. The round will be rated for all participants with a rating strictly less than 2100. You will have 2 hours to solve 6 problems.

Here is a big thank you to everyone involved in the round:

Looking forward to seeing everyone at the contest >~<

UPD: Scoring distribution: 500 — 1000 — 1500 — 2000 — 2500 — 3000

UPD2: Editorial

Full text and comments »

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

By FairyWinx, history, 4 years ago, translation, In English

Problem A. Idea by Igorbunov

Hint 1
Solution

Problem B. Idea by FairyWinx

Hint 1
Hint 2
Hint 3
Hint 4
Solution

Problem C. Idea by FairyWinx

Hint 1
Hint 2
Hint 3
Solution

Problem D. Idea by FairyWinx

Hint 1
Hint 2
Solution

Problem E. Idea by FairyWinx

Hint 1
Hint 2
Hint 3
Solution

Problem F. Idea by TeaTime, tutorial by purplesyringa

Editorialist's note: I didn't submit the solution myself, but I proved it theoretically, aggregated solutions of problemsetters as well as participants, so I'm fairly sure it's correct, but you might want to treat it with more suspicion.

Hint 1
Hint 2
Hint 3
Solution

Full text and comments »

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

By FairyWinx, history, 4 years ago, translation, In English

Приветствую, Кодефорсес ✿*∗˵╰༼✪ᗜ✪༽╯˵∗*✿

(Welcome, Codeforces on Russian)

TeaTime and I are happy to invite you to participate in Codeforces Round 818 (Div. 2). It will take place on Sep/02/2022 17:35 (Moscow time). The round will be rated for all participants with rating strictly lower than 2100. You will have 2 hours to solve 6 problems.

The standard place for thanks:

See you at the round🥰

Scoring distribution: 500 — 1000 — 1500 — 2000 — 2000 — 3000

UPD: Editorial!!! (Thanks to purplesyringa for English translation)

UPD: Winners!

Div 2:

Div 1:

Full text and comments »

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

By FairyWinx, 4 years ago, translation, In English

The following task is given: an array of integer $$$a_1, \ldots, a_n$$$ is given, as well as $$$q$$$ queries of one of two types:

  1. $$$a_i+=x$$$, where $$$l \leq i \leq r$$$.
  2. find out the number of indexes $$$i$$$, where $$$l\leq i\leq r$$$ and $$$a_j \lt a_i$$$, for all $$$j:$$$ $$$l \le j \lt i$$$. (Or humanly — the number of prefix maxima on the segment)

We want to solve this faster than for $$$O(sqrt(n))$$$ per request.

Let's consider an easier option when we don't have change requests. Then we can make a just Segment Tree, where a sorted list of prefix maxima is stored at the vertex, if our segment is the segment corresponding to the vertex of the segment tree. Then we should just make an algorithm, anological Merge Sort Tree, only we should consider the vertices into which we split the query from left to right and store the maximum among the previous elements on a suitable segment, and add to the answer the number of elements in the vertex larger than the maximum before, and then update the maximum.

It works for $$$O(log(n)^2)$$$ per request, as well as $$$O(n log(n))$$$ memory and time to build.


Note that this can be redone so that there are change requests. Then we only need to learn how to combine such lists and add value to them. And for this, for example, a persistent treap is suitable. Then we will store a persistent treap of all prefix maxima at the vertex. Then, when updating, if the vertex segment lies completely inside the query, then we will simply add the desired value to our treap (well, of course, we will push this value down). And to combine the lists, you just need to copy the values from the left subtree, and also select the desired suffix from the right subtree and copy it as well, and then combine these trees.

This already works for $$$O(log(n)^2)$$$ per request, but in this case there will be build for $$$O(nlog(n)^2)$$$, and, most importantly, memory will be $$$O((n +q)log(n)^2)$$$ at total.


Now the normal solution is for $$$O(n)$$$ memory and $$$O(log(n)^2)$$$ per request.

Let there be a just tree segment (the vertex $$$v$$$ has a left subtree — this is $$$v.l$$$, and the right one is $$$v.r$$$), then let us, for each vertex $$$v$$$, learn to count two values $$$cnt_v$$$ — the number of prefix maxima, if our segment is the segment corresponding to the vertex $$$v$$$, and $$$max_v$$$ is the maximum on the same segment.

Then we implement the function $$$f(v, x)$$$, which will count the number of prefix maxima of strictly large $$$x$$$ on the segment of the vertex $$$v$$$.

We have only three cases:

  1. If $$$v$$$ is a leaf, then everything is simple, you need to compare the value of this element with $$$x$$$.
  2. If $$$x\geq max_{v.l}$$$, then note that there are no exactly finding elements in the left subtree (since they are less than or equal to $$$x$$$), then we are only interested in the right subtree, that is, $$$f(v, x) = f(v.r, x)$$$.
  3. If $$$x \lt max_{v.l}$$$, then we are no longer interested in the value of $$$f(v.r, x)$$$, since the element with the value $$$max_{v.l}$$$ will definitely be among in the prefix maxima, so the number of prefix maxima on the right will be the same as and in the absence of a limit on $$$x$$$, and we already know this number — this is $$$cnt_v - cnt_{v.l}$$$, since we need the number of maxima on the right, and that's all except those on the left (logical, isn't it) (and it's not $$$cnt_{v.l}$$$, since in this case there may be elements less than $$$max_{v.l}$$$). So $$$f(v, x) = f(v.l, x) + cnt_v - cnt_{v.l}$$$.

This function works for $$$O(log(n))$$$, since each time we descend into exactly one subtree, and the depth of the tree of segments is just the logarithm.

It is clear that it is easy to solve the problem with this function, we can solve the problem, just like in the first case, only we will need to do not $$$lowerbound$$$ according to the list, but simply run this function. Building and the like is also trivial with this function. (All the subtleties can be found in the code)

implementation

Also thanks to Um_nik, who, in fact, came up with the last solution in a problem that boiled down to this and made it much more interesting)))

As well as examples of tasks for this technique 1, 2.

Full text and comments »

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

By FairyWinx, 4 years ago, translation, In English

Task A. Idea FairyWinx

Hint 1
Hint 2
Solution
Code

Задача B. Idea FairyWinx

Hint 1
Hint 2
Solution
Code

Задача C. Idea FairyWinx

Hint 1
Hint 1
Hint 2
Solution
Code

Задача D. Idea FairyWinx

An important fact
Hint 1.1
Hint 1.2
Hint 1.3
Solution 1
Code
Hint 2.1
Solution 2 (which almost everyone wrote)
Реализация

Задача E. Idea FairyWinx

Hint 1
Hint 2
Hint 3
Hint 4
Hint 5
Solution
Реализация

Задача F. Idea Igorbunov

Hint 1
Hint 2
Hint 3
Hint 4
Hint 5
Solution
Реализация

Full text and comments »

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

By FairyWinx, 4 years ago, translation, In English

Привки, Кодефорсес (ノ◕ヮ◕)ノ*:・゚✧

(Hello, Codeforces on Russian)

Igorbunov and I are happy to invite you to participate in Codeforces Round 777 (Div. 2), all the tasks of which will be about a little girl Madoka. It will take place on Mar/11/2022 17:35 (Moscow time). The round will be rated for all participants with rating strictly lower than 2100. You will have 2 hours to solve 6 problems.

I would also like to express my gratitude to the following people:

I wish you high rating, and I also hope that I will help you to distract from bad news at least a little ( ❤ ω ❤ )

Scoring distribution: 500 — 1250 — 1500 — 2000 —2500 — 3000

UPD1: Editorial

UPD2: Congratulations to the contest winners

Div 1+2

1 EvenImage 9457
2 Geothermal 9219
3 rainboy 8649
4 End. 8529
5 kshitij_sodani 8250

Div 2

1 shnirelman 6955
2 zzfzzfzzfzzf 6558
3 Kaname-Madoka 6539
4 peuch 6317
5 SnowySummer 6301

Full text and comments »

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

By FairyWinx, history, 5 years ago, In English

Fun fact one: Another account can liked comment in draft block, and it will get contribution.

Fun fact two: in one-two hour considred real contribution on comment/post from like.

And i'm conducted an experiment: call different color, and we put like on comment. And now i can tell: Blue get 3 contribution. Purple get 5 contribution. Yellow (2100-2299) get 8 contribution. Red (2400-2599) get 10 contribution. I don't know, this considered from now rating or max rating, and i don't get information for another color.

Full text and comments »

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