Neev4321's blog

By Neev4321, history, 17 months ago, In English

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.

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

»
17 months ago, hide # |
← Rev. 3  
Vote: I like it +25 Vote: I do not like it

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 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Thanks! Also, shouldn't $$$l = 2^k - 1$$$ since $$$\sum_{i=0}^{k - 1}{2^i} = 2^k - 1$$$?

    • »
      »
      »
      17 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Nope, there are $$$l = 2^k$$$ leaves, but we don't query any leaves, that's why the sum is only till $$$k - 1$$$.

»
17 months ago, hide # |
 
Vote: I like it +42 Vote: I do not like it

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 months ago, hide # ^ |
    ← Rev. 2  
    Vote: I like it +4 Vote: I do not like it

    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 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    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 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Mine used $$$7666$$$ queries.

    idea

    My code:

    code

    I was also shocked that it passed all tests

    • »
      »
      »
      17 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      can ternary search improve it?

      • »
        »
        »
        »
        17 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        No, because binary search takes $$$\lceil\log_2(l + 1)\rceil = 17$$$ queries but ternary search would take $$$2\lceil\log_3(l + 1)\rceil = 22$$$ queries.

    • »
      »
      »
      17 months ago, hide # ^ |
      ← Rev. 2  
      Vote: I like it 0 Vote: I do not like it

      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 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

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 months ago, hide # ^ |
    ← Rev. 2  
    Vote: I like it +3 Vote: I do not like it
    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}