제출 #643639

#제출 시각아이디문제언어결과실행 시간메모리
643639CyanmondOlympiads (BOI19_olympiads)C++17
100 / 100
516 ms1176 KiB
#include <bits/stdc++.h>

using i64 = int64_t;
constexpr int inf = 1 << 30;

int main()  {
    int N, K, C;
    std::cin >> N >> K >> C;

    std::vector<std::vector<int>> S(N, std::vector<int>(K));
    for (auto &vec : S) {
        for (auto &e : vec) {
            std::cin >> e;
        }
    }

    std::vector<std::vector<int>> event_scores(K);
    for (auto &vec : S) {
        for (int i = 0; i < K; ++i) {
            event_scores[i].push_back(vec[i]);
        }
    }
    for (auto &vec : event_scores) {
        std::sort(vec.begin(), vec.end(), std::greater());
        vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
    }

    struct data {
        int score_sum;
        std::vector<int> ids;
    };

    auto compare = [&](const data &a, const data &b) {
        return a.score_sum < b.score_sum;
    };
    
    auto get_unique_id = [&](const std::vector<int> &ids) {
        i64 res = 0;
        for (int i = 0; i < K; ++i) {
            res += ids[i];
            if (i != K - 1) {
                res *= (i64)event_scores[i + 1].size();
            }
        }
        return res;
    };

    std::priority_queue<data, std::vector<data>, decltype(compare)> heap(compare);
    int init_sum = 0;
    for (int i = 0; i < K; ++i) {
        init_sum += event_scores[i][0];
    }
    heap.push({init_sum, std::vector<int>(K)});
    std::unordered_set<i64> id_set;

    auto get_top = [&]() {
        const auto res = heap.top();
        id_set.insert(get_unique_id(res.ids));
        while ((not heap.empty()) and id_set.find(get_unique_id(heap.top().ids)) != id_set.end()) {
            heap.pop();
        }
        for (int i = 0; i < K; ++i) {
            if (res.ids[i] == (int)event_scores[i].size() - 1) {
                continue;
            }

            int new_sum = res.score_sum - event_scores[i][res.ids[i]];
            new_sum += event_scores[i][res.ids[i] + 1];
            auto new_ids = res.ids;
            ++new_ids[i];
            heap.push({new_sum, new_ids});
        }
        return res;
    };

    auto count_qt = [&](const std::vector<int> &ids) {
        std::vector dp(K + 1, std::vector(1 << K, 0));
        dp[0][0] = 1;

        for (int i = 0; i < N; ++i) {
            bool possible = true;
            int or_b = 0;
            for (int j = 0; j < K; ++j) {
                const auto limit = event_scores[j][ids[j]], score = S[i][j];
                if (limit < score) {
                    possible = false;
                    break;
                } else if (limit == score) {
                    or_b |= 1 << j;
                }
            }
            if (not possible) {
                continue;
            }


            for (int j = K - 1; j >= 0; --j) {
                for (int bit = 0; bit < (1 << K); ++bit) {
                    dp[j][bit] = std::min(dp[j][bit], C);
                    dp[j + 1][bit | or_b] += dp[j][bit];
                }
            }
        }

        return dp[K][(1 << K) - 1];
    };

    int count_top = 0;
    while (count_top < C) {
        const auto [score, ids] = get_top();

        const auto res = count_qt(ids);
        count_top += res;

        if (count_top >= C) {
            std::cout << score << std::endl;
        }
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...