Open In App

CSES Solutions - Concert Tickets

Last Updated : 08 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

There are N concert tickets available, each with a certain price given as array tickets[]. Then, M customers arrive, one after another. Each customer announces the maximum price they are willing to pay for a ticket given as array customer[], and after this, they will get a ticket with the nearest possible price such that it does not exceed the maximum price.

The task is to print, for each customer, the price that they will pay for their ticket. After this, the ticket cannot be purchased again. If a customer cannot get any ticket, print -1.

Examples:

Input: N = 5, tickets[] = {5, 3, 7, 8, 5}, M = 3, customer[] = {4, 8, 3}
Output:
3
8
-1
Explanation:

  • The first customer is willing to pay a maximum price of 4, so he will purchase the ticket with cost = 3.
  • The second customer is willing to pay a maximum price of 8, so he will purchase the ticket with cost = 8.
  • The third customer is willing to pay a maximum price of 3, but there are no tickets left with cost <= 3, so he won't be able to purchase any ticket.

Input: N = 4, tickets[] = {1, 1, 1, 1}, M = 4, customer[] = {1, 1, 1, 1}
Output:
1
1
1
1

Approach: To solve the problem, follow the below idea:

The problem can be solved by using upper bound and a frequency map. We can store all the tickets price in a map along with the frequency of each ticket. Now, for every customer[i], we can find the upper bound of customer[i] in the map, this will give us the ticket which has just greater price than what the customer can pay. Since, in a map all the pairs are sorted on the basis of key values, we can get the price by moving to the pair just before the upper bound to get the required ticket price. If there is no pair before it, print -1. Otherwise, decrease the frequency of the ticket by 1.

Step-by-step algorithm:

  • Maintain a map pendingTickets to store the count of each ticket corresponding to its cost.
  • Push the cost of all the tickets along with the count of each ticket.
  • For each customer, find the maximum cost of a ticket which does not exceed the limit of that customer using upper bound.
  • If such a ticket is found, print the cost of ticket, decrease the count of that ticket by 1 and move to the next customer.
  • Otherwise, print -1 for that customer.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>>
using namespace std;

vector<int> concertTickets(vector<int> &price , vector<int> &pay)
{
	// Create a multiset to store the prices of all tickets
	multiset<int> maxPrice;

	// Insert all the values of price array in the multiset
	for (int i = 0 ; i < price.size() ; i++)
	{
		maxPrice.insert(price[i]);
	}

	// Create an array answer to store the answer for each customer
	vector<int> ans(pay.size());

	// Now iterate through every customer
	for (int i = 0 ; i < pay.size() ; i++)
	{
		int temp = pay[i];

		// Find the upper bound of maximum price offered by customer in the multiset
		multiset<int>::iterator itr = maxPrice.upper_bound(temp);

		// If it points to the begining that means no ticket is available for the customer
		// Otherwise decrement the iterator and gets the value out of it and then erase that value from multiset
		if (itr == maxPrice.begin())
		{
			ans[i] = -1;
		}
		else
		{
			itr--;
			ans[i] = (*itr);
			maxPrice.erase(itr);
		}
	}

	// Retun the array answer
	return ans;
}

int main() {
    // Sample input
    vector<int> price = {5, 3, 7, 8, 5};
    vector<int> pay = {4,8,3};
    
    // Call the function to get the results
    vector<int> result = concertTickets(price, pay);
    
    // Print the result
    cout << "Result for each customer: ";
    for (int i : result) {
        cout << i << " ";
    }
    cout << endl;
    
    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;

public class GFG {

    // Function to find the upper bound in a sorted list
    static int upper_bound(ArrayList<Integer> arr, int k) {
        int low = 0;
        int high = arr.size() - 1;
        int ans = arr.size();
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (arr.get(mid) > k) {
                ans = mid;
                high = mid - 1;
            } 
            else {
                low = mid + 1;
            }
        }
        return ans;
    }

    // Function to find the best ticket each customer can buy
    public static ArrayList<Integer> concertTickets(ArrayList<Integer> price, ArrayList<Integer> pay) {
        // To store the prices of all tickets.
        ArrayList<Integer> maxPrice = new ArrayList<Integer>(price);
        
        // Sort the ticket prices in ascending order
        Collections.sort(maxPrice);
        
        // Create an array 'ans' to store the answer for each customer.
        ArrayList<Integer> ans = new ArrayList<Integer>();
        for (int i = 0; i < pay.size(); i++) {
            ans.add(0);
        }
        
        // Now iterate through every customer.
        for (int i = 0; i < pay.size(); i++) {
            int temp = pay.get(i);
            
            // Find the upper bound of maximum price offered by customer in the list.
            int itr = upper_bound(maxPrice, temp);
            
            // If it points to the beginning that means no ticket is available for the customer.
            if (itr == 0) {
                ans.set(i, -1);
            } else {
                // Decrement the iterator to get the actual index and then remove that ticket price from the list
                itr--;
                ans.set(i, maxPrice.get(itr));
                maxPrice.remove(itr);
            }
        }
        
        // Return the array answer.
        return ans;
    }

    public static void main(String[] args) {
        // Sample input
        ArrayList<Integer> price = new ArrayList<Integer>();
        ArrayList<Integer> pay = new ArrayList<Integer>();
        
        // Adding sample values
        for (int i : new int[]{5, 3, 7, 8, 5}) {
            price.add(i);
        }
        
        // Customer payments
        pay.add(4);
     	pay.add(8);
      	pay.add(3);
        
        // Call the function to get the results
        ArrayList<Integer> result = concertTickets(price, pay);
        
        // Print the result
        System.out.print("Result for each customer: ");
        for (int res : result) {
            System.out.print(res + " ");
        }
        System.out.println();
    }
}
Python
import bisect

def concertTickets(price , pay):

    # Create a multiset to store the prices of all tickets
    maxPrice = sorted(price)

    # Create an array answer to store the answer for each customer
    ans = [0 for j in range(len(pay))]

    # Now iterate through every customer
    for i in range(len(pay)):
    
        temp = pay[i]

        # Find the upper bound of maximum price offered by customer in the multiset
        itr = bisect.bisect(maxPrice,temp)

        # If it points to the beginning, that means no ticket is available for the customer
        # Otherwise, decrement the iterator and get the value out of it and then erase that value from the multiset
        if (itr == 0):
            ans[i] = -1
        else:
            itr -= 1
            ans[i] = maxPrice[itr]
            maxPrice.remove(ans[i])
        
    # Return the array answer
    return ans

def main():
    # Example ticket prices and customer offers
    ticket_prices = [5, 3, 7, 8, 5]
    customer_offers = [4, 8, 3]

    # Get the result from the concertTickets function
    results = concertTickets(ticket_prices, customer_offers)

    # Print the results
    print("Ticket prices assigned to customers:", results)

if __name__ == "__main__":
    main()
JavaScript
function concertTickets(price, pay) {
    // Create an array to store the result for each customer
    let ans = new Array(pay.length).fill(-1);
    
    // Create an array to mark which tickets have been sold
    let visited = new Array(price.length).fill(false);
    
    // Iterate through each customer
    for (let i = 0; i < pay.length; i++) {
        let maxPrice = -1;
        let index = -1;
        
        // Find the most expensive ticket that the current customer can afford and hasn't been sold
        for (let j = 0; j < price.length; j++) {
            if (price[j] <= pay[i] && !visited[j]) {
                if (maxPrice < price[j]) {
                    maxPrice = price[j];
                    index = j;
                }
            }
        }
        
        // If a valid ticket was found, mark it as sold and update the answer
        if (maxPrice !== -1) {
            ans[i] = maxPrice;
            visited[index] = true;
        }
    }
    
    return ans;
}

// Sample input
let price = [5, 3, 7, 8, 5];
let pay = [4, 8, 3];

// Call the function to get the results
let result = concertTickets(price, pay);

// Print the result
console.log("Result for each customer:", result);

Output
Result for each customer: 3 8 -1 

Time Complexity: O(N * logN + M * logN), where N is the number of tickets and M is the number of customers.
Auxiliary Space: O(N)


Next Article
Practice Tags :

Similar Reads