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

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

GIven this problem:

Given $$$n$$$ integer pairs $$$a_i$$$, $$$b_i$$$, pick $$$k$$$ of them so that $$$\frac{\sum_{}^{}a_i}{\sum_{}^{}b_i}$$$ is maximized, output the maximum value.

Constraints:

$$$1 \le k \le n \le 200000$$$

$$$1 \le a_i, b_i \le 10^{6}$$$

I have this scuffed greedy algorithm which does the following:

  1. Assume the result is $$$\ge x$$$, then let $$$u_i = a_i - xb_i$$$

  2. Greedily pick the largest $$$k$$$ values of $$$u_i$$$.

  3. Update $$$x$$$ to the new optimal value, if the new value is not better then stop.

After a lot of random tests, the worst case only made it perform $$$7$$$ iterations.

Are there any tests that makes it TLE, or at least run a lot more than $$$7$$$ iterations? If not, is there a proof? What is the runtime in the worst case?

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

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

Actually, this algorithm is known as Dinkelbach algorithm. If you invented it by yourself you must be a genius.

I think I can't prove it, but there are already some proof on the Internet. According to some informations, the worst-case number of iterations of the Dinkelbach algorithm is $$$O(\log(n C D)) \leq O(\log(n M))$$$, where $$$M = \max(C, D)$$$, where $$$C=\max(\max|c_i|,1),D=\max(\max|d_i|,1)$$$. (In this article, the pairs are indicated as $$$c_i, d_i$$$.)

Some other proof, I translated it into English using AI

I am only responsible for bringing these contents over, unfortunately I do not have the ability to verify the correctness of the content.

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

That's a cool algorithm.

Basically, you have $$$\binom{n}{k}$$$ options for the set of pairs you choose, each set $$$S$$$ will give some fraction $$$\frac{A_S}{B_S}$$$, which you then transform into a function $$$f_S(x) = A_S - B_S \cdot x$$$ which is linear. Then you construct a lower envelope (convex hull) of those lines, and then apply iteration to find a 0 of that lower envelope.

It can actually be shown that the lower envelope has at most $$$O(n^2)$$$ segments (maybe even some better bound is possible, but I don't know how), and it can be constructed in $$$O(n^2)$$$ time, but it is not really relevant to the iteration approach.

The iteration works as follows: we take $$$x_0 = 0$$$, then for $$$x_i$$$ we find the largest $$$f_S(x_i)$$$ and find $$$x_{i+1}$$$ as a 0 of $$$f_S(x)$$$. Let's denote the function we found for $$$x_i$$$ as $$$A_i - B_i \cdot x$$$, and $$$y_i = A_i - B_i \cdot x_i$$$. By the definition of $$$x_{i+1}$$$, $$$A_i - B_i \cdot x_{i+1} = 0$$$. Therefore, $$$y_i = B_i \cdot (x_{i+1} - x_i)$$$. $$$y_i$$$ is the largest value of our linear functions at $$$x_i$$$, so $$$A_{i+1} - B_{i+1} \cdot x_i \le y_i$$$. $$$y_{i+1} = A_{i+1} - B_{i+1} \cdot x_{i+1}$$$, which means $$$y_{i+1} + B_{i+1} \cdot (x_{i+1} - x_i) \le y_i$$$ and then $$$y_{i+1} \le \left( 1 - \frac{B_{i+1}}{B_i} \right) y_i$$$.

From this we can conclude that $$$B_{i+1} \le \frac{1}{2} B_i$$$ or $$$y_{i+1} \le \frac{1}{2} y_i$$$ (or both). $$$y_{i+1} = A_{i+1} - B_{i+1} \cdot x_{i+1} = A_{i+1} - \frac{B_{i+1}}{B_i} A_{i}$$$. $$$B_i$$$ are positive integers, $$$y_i$$$ are non-negative rational numbers with both numerators and denominators bounded by $$$(\max A_i) \cdot (\max B_i)$$$. Therefore, after $$$O(\log ((\max A_i) \cdot (\max B_i)))$$$ iterations we must have $$$y_i = 0$$$.