<p>There are <code>n</code> workers. You are given two integer arrays <code>quality</code> and <code>wage</code> where <code>quality[i]</code> is the quality of the <code>i<sup>th</sup></code> worker and <code>wage[i]</code> is the minimum wage expectation for the <code>i<sup>th</sup></code> worker.</p>

<p>We want to hire exactly <code>k</code> workers to form a <strong>paid group</strong>. To hire a group of <code>k</code> workers, we must pay them according to the following rules:</p>

<ol>
	<li>Every worker in the paid group must be paid at least their minimum wage expectation.</li>
	<li>In the group, each worker&#39;s pay must be directly proportional to their quality. This means if a worker&rsquo;s quality is double that of another worker in the group, then they must be paid twice as much as the other worker.</li>
</ol>

<p>Given the integer <code>k</code>, return <em>the least amount of money needed to form a paid group satisfying the above conditions</em>. Answers within <code>10<sup>-5</sup></code> of the actual answer will be accepted.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> quality = [10,20,5], wage = [70,50,30], k = 2
<strong>Output:</strong> 105.00000
<strong>Explanation:</strong> We pay 70 to 0<sup>th</sup> worker and 35 to 2<sup>nd</sup> worker.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> quality = [3,1,10,10,1], wage = [4,8,2,2,7], k = 3
<strong>Output:</strong> 30.66667
<strong>Explanation:</strong> We pay 4 to 0<sup>th</sup> worker, 13.33333 to 2<sup>nd</sup> and 3<sup>rd</sup> workers separately.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>n == quality.length == wage.length</code></li>
	<li><code>1 &lt;= k &lt;= n &lt;= 10<sup>4</sup></code></li>
	<li><code>1 &lt;= quality[i], wage[i] &lt;= 10<sup>4</sup></code></li>
</ul>

# want to form a paid group of size k
# each worker needs AT LEAST the min wage[i]
# but within the group, they must be paid in proportion to quality q[i]/Q_group

# exponential size LP (constraints on subsets)
# for any group:
# payment is AT LEAST sum of wages
# the scaling is determined by the individual with the highest wage/quality,
# everyone else in the group is getting paid according to that "rate"
# so as the employer we want to build a group out of individuals minimizing wage/quality

# is this even the right logic?
# it looks like if we select very high quality we can use it to quash the payout to others?

# select the min k wage/quality as R
# then the cost is max(R) * sum_qualities_in_R
# maybe better to maintain R as indices into quality/wage with a lambda

# since the input isn't sorted there's not much better we can do than sorting or minheap

# rather than computing the individual rates, might be greedy alg
# maintain the MAX MIN WAGE / TOTAL QUALITY of the group
# with new workers, swap them in if it decreases the ratio
# how to check if we can swap?
# if they aren't going to raise the min wage then check if they raise quality
# if they are going to raise the min wage, then check if replacing the min quality guy would improve ratio
# so minheap over qualities (or sort by quality and just pop)


# here's how i understand this reference solution
# let rate = wage/quality
# then, cost is max_rate_in_group * sum_quality_of_group
# to minimize cost, we can try to reduce either value
# so, sort candidates by rate first (minimizing first half), then try to greedily substitute candidates for minimizing the second half while potentially increasing first
#   i.e., each substitute is by removing the max quality in-group
#   of course, this can increase the max rate
# and output the best cost we found

class Solution:
    def mincostToHireWorkers(self, quality: List[int], wage: List[int], k: int) -> float:
        by_rate = sorted([i for i in range(len(quality))], key=lambda i: wage[i]/quality[i])
        pq = [] # maxheap on quality
        max_rate = 0.0
        qsum = 0

        for i in by_rate[:k]:
            max_rate = wage[i]/quality[i]
            qsum += quality[i]
            heapq.heappush(pq, -quality[i])

        res = max_rate * qsum

        for i in by_rate[k:]:
            max_rate = wage[i]/quality[i]
            qsum += quality[i] + heapq.heappop(pq)
            heapq.heappush(pq, -quality[i])
            res = min(res, max_rate * qsum)
        
        return res
            


        return 0

18500