제출 #1308110

#제출 시각아이디문제언어결과실행 시간메모리
1308110orosmoriFestival (IOI25_festival)C++20
5 / 100
51 ms9784 KiB
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

// Structure to keep track of coupon details along with their original index
struct Coupon {
    int id;
    long long p;
    long long t;
};

// Comparator for high-type coupons (T > 1)
// Sorts based on the key: (P * T) / (T - 1)
// We compare a < b by cross-multiplying: 
// a.p * a.t * (b.t - 1) < b.p * b.t * (a.t - 1)
bool compareHigh(const Coupon& a, const Coupon& b) {
    long long valA = a.p * a.t * (b.t - 1);
    long long valB = b.p * b.t * (a.t - 1);
    if (valA != valB) {
        return valA < valB;
    }
    return a.p < b.p; // Tie-breaker
}

std::vector<int> max_coupons(int A, std::vector<int> P, std::vector<int> T) {
    int n = P.size();
    vector<Coupon> high; // Stores coupons with T > 1
    vector<Coupon> ones; // Stores coupons with T = 1

    for (int i = 0; i < n; ++i) {
        if (T[i] == 1) {
            ones.push_back({i, (long long)P[i], (long long)T[i]});
        } else {
            high.push_back({i, (long long)P[i], (long long)T[i]});
        }
    }

    // 1. Sort High coupons by the optimal greedy key
    sort(high.begin(), high.end(), compareHigh);
    
    // 2. Sort T=1 coupons by Price (cheapest first)
    sort(ones.begin(), ones.end(), [](const Coupon& a, const Coupon& b) {
        return a.p < b.p;
    });

    // 3. Precompute prefix sums for T=1 coupons to allow O(log N) queries
    int m = ones.size();
    vector<long long> ones_pref(m + 1, 0);
    for (int i = 0; i < m; ++i) {
        ones_pref[i+1] = ones_pref[i] + ones[i].p;
    }

    int best_total_count = -1;
    vector<int> best_selection;

    // 4. Iterate through possible counts of High coupons.
    // Due to Subtask 6 constraints, tokens decrease exponentially for T >= 2.
    // We can't buy more than ~60 high-type coupons before running out of tokens (since A <= 10^9).
    // We take a safe upper bound of 70 or the size of the high list.
    int max_k = min((int)high.size(), 75); 

    for (int k = 0; k <= max_k; ++k) {
        long long current_tokens = A;
        bool possible = true;
        vector<int> current_indices;
        
        // Try buying the first k high coupons in sorted order
        for (int i = 0; i < k; ++i) {
            if (current_tokens >= high[i].p) {
                current_tokens = (current_tokens - high[i].p) * high[i].t;
                current_indices.push_back(high[i].id);
            } else {
                possible = false;
                break;
            }
        }

        if (possible) {
            // We have 'current_tokens' left. Fill with cheapest T=1 coupons.
            // Find the largest index in prefix sum such that sum <= current_tokens
            auto it = upper_bound(ones_pref.begin(), ones_pref.end(), current_tokens);
            int count_ones = (int)(it - ones_pref.begin()) - 1; 
            
            // Check if this combination is the best so far
            if (k + count_ones > best_total_count) {
                best_total_count = k + count_ones;
                best_selection = current_indices; // First the high coupons
                // Then append the ones
                for (int i = 0; i < count_ones; ++i) {
                    best_selection.push_back(ones[i].id);
                }
            }
        } else {
            // Optimization: If we can't afford the first k (sorted by "efficiency"),
            // we likely can't afford k+1. We can break here.
            break;
        }
    }

    return best_selection;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...