<p>You are given <code>n</code> item&#39;s value and label as two integer arrays <code>values</code> and <code>labels</code>. You are also given two integers <code>numWanted</code> and <code>useLimit</code>.</p>

<p>Your task is to find a subset of items with the <strong>maximum sum</strong> of their values such that:</p>

<ul>
	<li>The number of items is <strong>at most</strong> <code>numWanted</code>.</li>
	<li>The number of items with the same label is <strong>at most</strong> <code>useLimit</code>.</li>
</ul>

<p>Return the maximum sum.</p>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">values = [5,4,3,2,1], labels = [1,1,2,2,3], numWanted = 3, useLimit = 1</span></p>

<p><strong>Output:</strong> <span class="example-io">9</span></p>

<p><strong>Explanation:</strong></p>

<p>The subset chosen is the first, third, and fifth items with the sum of values 5 + 3 + 1.</p>
</div>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">values = [5,4,3,2,1], labels = [1,3,3,3,2], numWanted = 3, useLimit = 2</span></p>

<p><strong>Output:</strong> <span class="example-io">12</span></p>

<p><strong>Explanation:</strong></p>

<p>The subset chosen is the first, second, and third items with the sum of values 5 + 4 + 3.</p>
</div>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">values = [9,8,8,7,6], labels = [0,0,0,1,1], numWanted = 3, useLimit = 1</span></p>

<p><strong>Output:</strong> <span class="example-io">16</span></p>

<p><strong>Explanation:</strong></p>

<p>The subset chosen is the first and fourth items with the sum of values 9 + 7.</p>
</div>

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

<ul>
	<li><code>n == values.length == labels.length</code></li>
	<li><code>1 &lt;= n &lt;= 2 * 10<sup>4</sup></code></li>
	<li><code>0 &lt;= values[i], labels[i] &lt;= 2 * 10<sup>4</sup></code></li>
	<li><code>1 &lt;= numWanted, useLimit &lt;= n</code></li>
</ul>

class Solution {

public:
    int largestValsFromLabels(vector<int>& values, vector<int>& labels, int numWanted, int useLimit) {
        
        vector<pair<int,int>> items(values.size());
        for( size_t idi = 0; idi < items.size(); ++idi ) {
            items[idi] = { values[idi], labels[idi] };
        }

        std::sort( items.begin(), items.end(), [](const auto &a, const auto &b) {
            if( a.first == b.first ){
                return a.second > a.second;
            }
            return a.first > b.first;
        });

        int maxSum = 0;
        int pickedC = 0;
        map<int,int> mlabels;
        for( size_t idi = 0; idi < items.size() && pickedC < numWanted; ++idi ) {
            const int label = items[idi].second;
            if( mlabels.find(label) == mlabels.end() ){
                mlabels[label] = 0;
            }
            if( mlabels[label] >= useLimit){
                continue;
            }
            ++mlabels[label];
            ++pickedC;
            maxSum += items[idi].first;
        }

        return maxSum;
    }

/* HEAVY SOLUTION
private:

    int computeMaxSum(vector<int> &pickedIndexes, vector<pair<int,int>> &items, const int &useLimit ){


        vector<pair<int,int>> pickedItems;
        for( size_t idi = 0; idi < pickedIndexes.size(); ++idi ) {
            //cout << pickedIndexes[idi] << " ";
            pickedItems.push_back( items[pickedIndexes[idi]]  );
        }
        std::sort( pickedItems.begin(), pickedItems.end(), [](const auto &a, const auto &b) {
            if( a.first == b.first ){
                return a.second > a.second;
            }
            return a.first > b.first;
        });

        int tmpSum = 0;
        map<int,int> mlabels;

        for( size_t idi = 0; idi < pickedItems.size(); ++idi ) {


            const int label = pickedItems[idi].second;
            if( mlabels.find(label) == mlabels.end() ){
                mlabels[label] = 0;
            } else {
                if( mlabels[label] >= useLimit ) {
                    continue; // I cannot use the item
                }
            }
            ++mlabels[label];

            tmpSum += pickedItems[idi].first;
        }
        //cout << endl;

        return tmpSum;

    }

    bool getNext(vector<int> &pickedIndexes, const int &numToPick, const int &numItems){
        if( pickedIndexes.size() == 0 ){
            for( size_t idp = 0; idp < numToPick; ++idp ) {
                pickedIndexes.push_back( static_cast<int>(idp) );
            }
            return true;
        }

        for( size_t idp = 0; idp < numToPick; ++idp ) {
            if( idp +1 < numToPick ) {
                if( pickedIndexes[idp] < pickedIndexes[idp+1]-1 ) {
                    ++pickedIndexes[idp];
                    for( size_t idl = 0; idl < idp; ++idl ) {
                        pickedIndexes[idl] = static_cast<int>(idl) ;
                    }
                    return true;
                }
            } else { // last one
                if( pickedIndexes[idp] < numItems-1 ) {
                    ++pickedIndexes[idp];
                    for( size_t idp = 0; idp < numToPick-1; ++idp ) {
                        pickedIndexes[idp] = static_cast<int>(idp) ;
                    }
                    return true;
                }
            }
        }

        return false;
    }

public:
    int largestValsFromLabels(vector<int>& values, vector<int>& labels, int numWanted, int useLimit) {
        
        vector<pair<int,int>> items(values.size());
        for( size_t idi = 0; idi < items.size(); ++idi ) {
            items[idi] = { values[idi], labels[idi] };
        }

        vector<int> pickedIndexes;

        int maxSum = 0;
        int tmpSum = 0;
        while(getNext(pickedIndexes, numWanted, items.size())) {

            tmpSum = computeMaxSum(pickedIndexes, items, useLimit );
            if( tmpSum > maxSum ) {
                maxSum = tmpSum;
            }
        }
        return maxSum;
    }
    */
};
23900