This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "tickets.h"
#include <algorithm>
#include <cassert>
#include <vector>
#include <set>
long long find_maximum(int numRounds, std::vector<std::vector<int>> ticket) {
    int numColors = ticket.size();
    int numRanks = ticket[0].size();
    auto plusCount = std::vector<int>(numColors, 0);
    auto minusCount = std::vector<int>(numColors, 0);
    for (int color = 0; color < numColors; ++color) {
        if (color % 2 == 0)
            plusCount[color] = numRounds;
        else
            minusCount[color] = numRounds;
    }
    auto getPlusToMinus = [&](int color) -> int {
        assert(plusCount[color] > 0);
        int plusValue = ticket[color][numRanks - 1 - (plusCount[color] - 1)];
        int minusValue = ticket[color][minusCount[color]];
        return -(plusValue + minusValue);
    };
    auto getMinusToPlus = [&](int color) -> int {
        assert(minusCount[color] > 0);
        int plusValue = ticket[color][numRanks - 1 - plusCount[color]];
        int minusValue = ticket[color][minusCount[color] - 1];
        return plusValue + minusValue;
    };
    auto plusToMinus = std::set<std::pair<int, int>>();
    auto minusToPlus = std::set<std::pair<int, int>>();
    for (int color = 0; color < numColors; ++color) {
        if (minusCount[color] > 0) {
            minusToPlus.insert({-getMinusToPlus(color), color});  // want largest one
        }
        if (plusCount[color] > 0) {
            plusToMinus.insert({-getPlusToMinus(color), color}); // want smallest one
        }
    }
    while (true) {
        // Iterate over the set of feasible solutions,
        // and do swaps as long as they are net profitable.
        auto minusToPlusItem = *minusToPlus.begin();
        auto plusToMinusItem = *plusToMinus.begin();
        // Step 1: Erase all items that involve the two colors.
        minusToPlus.erase(minusToPlusItem);
        if (plusCount[minusToPlusItem.second] > 0)
            plusToMinus.erase({-getPlusToMinus(minusToPlusItem.second), minusToPlusItem.second});
        plusToMinus.erase(plusToMinusItem);
        if (minusCount[plusToMinusItem.second] > 0)
            minusToPlus.erase({-getMinusToPlus(plusToMinusItem.second), plusToMinusItem.second});
        // Step 2: Check if doing the swap is profitable.
        minusToPlusItem.first = -minusToPlusItem.first;
        plusToMinusItem.first = -plusToMinusItem.first;
        if (minusToPlusItem.first + plusToMinusItem.first <= 0)
            break;
        // Step 3: Do the swap.
        int color1 = minusToPlusItem.second;
        int color2 = plusToMinusItem.second;
        minusCount[color1]--;
        plusCount[color1]++;
        minusCount[color2]++;
        plusCount[color2]--;
        // Step 4: Update the data structures with the new swap candidates.
        for (int color : {color1, color2}) {
            if (minusCount[color] > 0) {
                minusToPlus.insert({-getMinusToPlus(color), color});  // want largest one
            }
            if (plusCount[color] > 0) {
                plusToMinus.insert({-getPlusToMinus(color), color}); // want smallest one
            }
        }
    }
    long long res = 0;
    for (int color = 0; color < numColors; ++color) {
        assert(plusCount[color] + minusCount[color] == numRounds);
        for (int index = 0; index < minusCount[color]; ++index) res -= ticket[color][index];
        for (int index = 0; index < plusCount[color]; ++index) res += ticket[color][numRanks - 1 - index];
    }
    auto answer = std::vector<std::vector<int>>(numColors, std::vector<int>(numRanks, -1));
    auto countPerRound = std::vector<std::pair<int, int>>();
    for (int round = 0; round < numRounds; ++round) countPerRound.push_back({0, round});
    // Step 5: Construct the actual assignment of tickets.
    auto plusColors = std::vector<int>(numColors);
    for (int color = 0; color < numColors; ++color) plusColors[color] = color;
    for (int round = 0; round < numRounds; ++round) {
        std::sort(plusColors.begin(), plusColors.end(), [&](int lhs, int rhs) -> bool {
            return plusCount[lhs] > plusCount[rhs];
        });
        auto marked = std::vector<bool>(numColors, false);
        for (int index = 0; index < numColors / 2; ++index) {
            int color = plusColors[index];
            assert(plusCount[color] > 0);
            answer[color][numRanks - 1 - (plusCount[color] - 1)] = round;
            --plusCount[color];
            marked[color] = true;
        }
        for (int color = 0; color < numColors; ++color) if (!marked[color]) {
            assert(minusCount[color] > 0);
            answer[color][minusCount[color] - 1] = round;
            --minusCount[color];
        }
    }
	allocate_tickets(answer);
    return res;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |