Блог пользователя Neev4321

Автор Neev4321, история, 17 месяцев назад, По-английски

I was solving the problem Finding Routers in the practice session of APIO 2025. I intuited (guessed) the following solution.

code

It gives the full 100 points but I have no proof of its correctness. It has an obvious $$$n\log_2{l}$$$ upper bound on the number of use_detector calls. This accounts for the first 3 subtasks. I think this bound can be further improved to $$$2n\log_2(\frac{l}{2n})$$$. However, none of these bounds explain why it can solve subtask 4 within $$$7500$$$ queries.

I found this blog post but the commentor also had no proof of his solution. I also found this solution which caches the queries. I think (not sure) it asks the same queries as my solution. It might be easier to reason about.

  • Проголосовать: нравится
  • +34
  • Проголосовать: не нравится

»
17 месяцев назад, скрыть # |
← Rev. 3  
Проголосовать: нравится +25 Проголосовать: не нравится

Imagine the D&C as a binary tree with some good leaves. In each level, you will either have less than $$$n$$$ nodes. In this case, all nodes can have good children, so you will query all of them. Or you will have more than $$$n$$$ nodes, and obviously, at most $$$n$$$ of them can have good children, so you will query only $$$n$$$ of them.

We also know that a level $$$i$$$ has exactly $$$2^i$$$ nodes. So if we let $$$l = 2^k$$$, the total number of queries is

$$$Q = \sum\limits_{i = 0}^{k-1} {\min(2^i, n)} = \sum\limits_{i = 0}^{\lfloor\log_2{n}\rfloor} {2^i} + (k - 1 - \lfloor\log_2{n}\rfloor) \cdot n = 2^{\lfloor\log_2{n}\rfloor + 1} - 1 + (k - 1 - \lfloor\log_2{n}\rfloor) \cdot n$$$

By letting $l = 2^{16}$, we get $$$Q = 7023$$$ and letting $$$l = 2^{17}$$$, we get $$$Q = 8023$$$, so we know that for $$$l = 10^5$$$, $$$7023 \le Q \le 8023$$$. I don't think finding a closed formula for a non power of two value of $$$l$$$ is trivial, so in these cases it's better to code and see.

Pre 2020 IOI Spoiler
»
17 месяцев назад, скрыть # |
 
Проголосовать: нравится +42 Проголосовать: не нравится

I remained skeptical even after seeing MinaRagy06's bounds. Because, a binary tree with $$$10^5$$$ nodes would need $$$17$$$ layers. Make the first $$$16$$$ layers into a complete binary tree. Then, the last layer would have $$$34465$$$ nodes. Since $$$34465 \ge n$$$, the bound on the number of queries when $$$l=10^5$$$ should be similar to the bound when $$$l = 2^{17}$$$.

Finally, I prepared a countercase.

Countercase Generator
Countercase

My code used $$$7993$$$ queries on the countercase!
The cache solution used $$$7596$$$ queries.

I am pretty confident that I can hack any solution that is a variation of mine (uses first instead of last, uses inclusive range, does not use std::max, etc). So, does someone have a deterministic solution for solving subtask 4 using $$$7500$$$ queries?

  • »
    »
    17 месяцев назад, скрыть # ^ |
    ← Rev. 2  
    Проголосовать: нравится +4 Проголосовать: не нравится

    Ohh.. my bad.

    I've checked the model solution from the official IOI 2020 website. After adjusting your generator, it took more than $$$8200$$$ queries, and after reading it, I found that it queries the leaves, taking $$$n$$$ extra queries. So apparently there are no correct solutions to the problem :clown:

  • »
    »
    17 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Okay, so I've tried to combine the queries caching optimization with my old 96.64 points solution, which uses binary search + square root decomposition, and it got $$$100$$$ points, and I wasn't able to hack it. However, I couldn't find any upper bounds better than $$$8500$$$ (the upper bound before caching queries), but I believe it would be really hard to hack because its behavior is very messy.

    Code
  • »
    »
    17 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Mine used $$$7666$$$ queries.

    idea

    My code:

    code

    I was also shocked that it passed all tests

    • »
      »
      »
      17 месяцев назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      can ternary search improve it?

    • »
      »
      »
      17 месяцев назад, скрыть # ^ |
      ← Rev. 2  
      Проголосовать: нравится 0 Проголосовать: не нравится

      I have found a proof for your solution.

      Let's create a binary search tree representing the search on the range $$$[0, l]$$$. Starting from root node, we can observe how many points will not use any query on this level. So, the root node — midpoint of the range will be asked once, for the next points, we have its value in memory, that's why we lose $$$n-1$$$ queries. Then in the second level of the tree, there are two nodes and they both will be asked once, again we lose $$$n-2$$$ queries. And this continues. In total, we use $$$n*log2(l)-(n-1)-(n-2)-(n-4)-...$$$ queries.

      I hope, I explained it correctly.))

»
17 месяцев назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

I think this bound can be further improved to $$$2n\log_2(\frac{l}{2n})$$$

Can you elaborate? If that is true, I think the problem would be solvable in $$$\approx 4000$$$ queries with the solution from my previous comment.

  • »
    »
    17 месяцев назад, скрыть # ^ |
    ← Rev. 2  
    Проголосовать: нравится +3 Проголосовать: не нравится
    Proof

    Initially, I had only analyzed it roughly and made crude assumptions about $$$l$$$, $$$s$$$ (so no need for ceil in equation), etc. This is a more correct bound. I hope it is strong enough for your algorithm.

    Edit: \begin{equation}\lfloor 2n\log_2(\frac{\sqrt{8}(l + 1)}{3n} + \frac{2\sqrt{8}}{3})\rfloor = 13174\end{equation}