📜  售票后利润最大化|设置 2(对于 [1, 10^6] 范围内的元素)

📅  最后修改于: 2021-10-26 07:02:10             🧑  作者: Mango

给定一个大小为N的数组arr[] ,其中 arr[i] 表示票数、第 i 个卖家拥有的票数和一个正整数K 。门票的价格是售票员剩余的门票数量。他们总共可以卖出K张票。找出他们通过出售 K 票可以获得的最大金额。以10 9 + 7 为模数给出答案

例子:

方法:本文讨论了幼稚的方法和有效的方法。
文章中提到的方法可以通过观察进一步优化,因为所有元素都小于或等于 10^6 ,因此,我们可以将所有元素的频率存储在数组 A[] 中。请按照以下步骤解决问题:

  • 创建一个数组A[] ,用于存储数组arr[]的每个元素的频率。
  • 使用变量i在范围[0, N-1] 中迭代并将A[arr[i]]的值增加1
  • 初始化一个变量,比如j ,它跟踪数组元素的位置。
  • 使用变量i在范围[0, 1000000] 中迭代并执行以下步骤:
    • A[i] != 0 时,将arr[j]的值修改为 i 并将A[i]的值减1
  • 初始化两个变量,假设iN-1jN-2
  • 初始化一个变量,比如ans0
  • k>0j>=0 时迭代并执行以下步骤:
    1. 如果arr[i] > arr[j]
      • 然后将min(K, ij)*arr[i] 添加到答案中。
      • K的值减少ij并将 arr[i] 的值减少 1。
    2. 除此以外,
      • arr[j] = arr[i] 时递减j的值。
      • 然后将min(K, ij)*arr[i] 添加到答案ans 中
      • K的值减少ij并将 arr[i] 的值减少 1。
  • 迭代而K>0arr[i]>0并执行以下步骤:
    • 然后将min(K, N)*arr[i] 添加到答案ans 中
    • K的值减少N,并将 arr[i] 的值减少 1。
  • 执行完上述步骤后,打印ans的值作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find maximum profit
// after selling K tickets
int maxAmount(int n, int k, int arr[])
{
    // Frequency array to store freq
    // of every element of the array
    int A[1000001] = { 0 };
    for (int i = 0; i < n; i++) {
        A[arr[i]]++;
    }
 
    int j = 0;
    // Modify the arr[] so that the
    // array is sorted in O(N)
    for (int i = 0; i < 1000001; i++) {
        while (A[i] != 0) {
            arr[j++] = i;
            A[i]--;
        }
    }
 
    // Variable to store answer
    long long int ans = 0;
    int mod = 1e9 + 7;
    int i = n - 1;
    j = n - 2;
 
    // Traverse the array while K>0
    // and j>=0
    while (k > 0 && j >= 0) {
 
        // If arr[i] > arr[j] then
        // ticket can be brought from
        // counter [j+1, N]
        if (arr[i] > arr[j]) {
            ans = ans + min(k, (i - j)) * arr[i];
            k = k - (i - j);
            arr[i]--;
        }
        else {
 
            // If arr[j] == arr[i] decrement j until
            // arr[j] != arr[i]
            while (j >= 0 && arr[j] == arr[i])
                j--;
            if (j < 0)
                break;
 
            // Sell tickets from counter [j+1, N]
            ans = ans + min(k, (i - j)) * arr[i];
            k = k - (i - j);
            arr[i]--;
        }
    }
 
    // All elements of array are equal
    // Send tickets from each counter 1
    // time until K > 0.
    while (k > 0 && arr[i] != 0) {
        ans = ans + min(n, k) * arr[i];
        k -= n;
        arr[i]--;
    }
    ans = ans % mod;
 
    // Converting answer from long long
    // to int
    int x = ans;
    return x;
}
 
// Driver Code
int main()
{
    // Given Input
    int n = 5;
    int k = 3;
    int arr[n] = { 4, 3, 6, 2, 4 };
 
    // Function Call
    int ans = maxAmount(n, k, arr);
    cout << ans;
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find maximum profit
// after selling K tickets
static int maxAmount(int n, int k, int arr[])
{
    // Frequency array to store freq
    // of every element of the array
    int A[] = new int[1000001];
    for (int i = 0; i < n; i++) {
        A[arr[i]]++;
    }
 
    int j = 0;
   
    // Modify the arr[] so that the
    // array is sorted in O(N)
    for (int i = 0; i < 1000001; i++) {
        while (A[i] != 0) {
            arr[j++] = i;
            A[i]--;
        }
    }
 
    // Variable to store answer
    int ans = 0;
    int mod = (int) (1e9 + 7);
    int i = n - 1;
    j = n - 2;
 
    // Traverse the array while K>0
    // and j>=0
    while (k > 0 && j >= 0) {
 
        // If arr[i] > arr[j] then
        // ticket can be brought from
        // counter [j+1, N]
        if (arr[i] > arr[j]) {
            ans = ans + Math.min(k, (i - j)) * arr[i];
            k = k - (i - j);
            arr[i]--;
        }
        else {
 
            // If arr[j] == arr[i] decrement j until
            // arr[j] != arr[i]
            while (j >= 0 && arr[j] == arr[i])
                j--;
            if (j < 0)
                break;
 
            // Sell tickets from counter [j+1, N]
            ans = ans + Math.min(k, (i - j)) * arr[i];
            k = k - (i - j);
            arr[i]--;
        }
    }
 
    // All elements of array are equal
    // Send tickets from each counter 1
    // time until K > 0.
    while (k > 0 && arr[i] != 0) {
        ans = ans + Math.min(n, k) * arr[i];
        k -= n;
        arr[i]--;
    }
    ans = ans % mod;
 
    // Converting answer from long long
    // to int
    int x = ans;
    return x;
}
 
// Driver Code
public static void main(String[] args)
{
    // Given Input
    int n = 5;
    int k = 3;
    int arr[] = { 4, 3, 6, 2, 4 };
 
    // Function Call
    int ans = maxAmount(n, k, arr);
    System.out.print(ans);
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python3 program for the above approach
 
# Function to find maximum profit
# after selling K tickets
def maxAmount(n, k, arr):
     
    # Frequency array to store freq
    # of every element of the array
    A = [0 for i in range(1000001)]
    for i in range(n):
        A[arr[i]] += 1
 
    j = 0
     
    # Modify the arr[] so that the
    # array is sorted in O(N)
    for j in range(1000001):
        while(A[i] != 0):
            arr[j] = i;
            j += 1
            A[i] -= 1
 
    # Variable to store answer
    ans = 6
    mod = 1000000007
    i = n - 1
    j = n - 2
 
    # Traverse the array while K>0
    # and j>=0
    while (k > 0 and j >= 0):
         
        # If arr[i] > arr[j] then
        # ticket can be brought from
        # counter [j+1, N]
        if (arr[i] > arr[j]):
            ans = ans + min(k, (i - j)) * arr[i]
            k = k - (i - j)
            arr[i] -= 1
        else:
             
            # If arr[j] == arr[i] decrement j until
            # arr[j] != arr[i]
            while (j >= 0 and arr[j] == arr[i]):
                j -= 1
                 
            if (j < 0):
                break
 
            # Sell tickets from counter [j+1, N]
            ans = ans + min(k, (i - j)) * arr[i]
            k = k - (i - j)
            arr[i] -= 1
 
    # All elements of array are equal
    # Send tickets from each counter 1
    # time until K > 0.
    while (k > 0 and arr[i] != 0):
        ans = ans + min(n, k) * arr[i]
        k -= n
        arr[i] -= 1
 
    ans = ans % mod
 
    # Converting answer from long long
    # to int
    x = ans
    return x
 
# Driver Code
if __name__ == '__main__':
     
    # Given Input
    n = 5
    k = 3
    arr = [ 4, 3, 6, 2, 4 ]
 
    # Function Call
    ans = maxAmount(n, k, arr)
    print(ans)
 
# This code is contributed by avijitmondal1998


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find maximum profit
// after selling K tickets
static int maxAmount(int n, int k, int []arr)
{
    // Frequency array to store freq
    // of every element of the array
  int i;
    int []A = new int[1000001];
    Array.Clear(A,0,1000001);
    for (i = 0; i < n; i++) {
        A[arr[i]]++;
    }
 
    int j = 0;
    // Modify the arr[] so that the
    // array is sorted in O(N)
    for (i = 0; i < 1000001; i++) {
        while (A[i] != 0) {
            arr[j++] = i;
            A[i]--;
        }
    }
 
    // Variable to store answer
    int ans = 0;
    int mod = 1000000007;
    i = n - 1;
    j = n - 2;
 
    // Traverse the array while K>0
    // and j>=0
    while (k > 0 && j >= 0) {
 
        // If arr[i] > arr[j] then
        // ticket can be brought from
        // counter [j+1, N]
        if (arr[i] > arr[j]) {
            ans = ans + Math.Min(k, (i - j)) * arr[i];
            k = k - (i - j);
            arr[i]--;
        }
        else {
 
            // If arr[j] == arr[i] decrement j until
            // arr[j] != arr[i]
            while (j >= 0 && arr[j] == arr[i])
                j--;
            if (j < 0)
                break;
 
            // Sell tickets from counter [j+1, N]
            ans = ans + Math.Min(k, (i - j)) * arr[i];
            k = k - (i - j);
            arr[i]--;
        }
    }
 
    // All elements of array are equal
    // Send tickets from each counter 1
    // time until K > 0.
    while (k > 0 && arr[i] != 0) {
        ans = ans + Math.Min(n, k) * arr[i];
        k -= n;
        arr[i]--;
    }
    ans = ans % mod;
 
    // Converting answer from long long
    // to int
    int x = ans;
    return x;
}
 
// Driver Code
public static void Main()
{
    // Given Input
    int n = 5;
    int k = 3;
    int []arr = { 4, 3, 6, 2, 4 };
 
    // Function Call
    int ans = maxAmount(n, k, arr);
    Console.Write(ans);
}
}
 
// This code is contributed by ipg2016107.


Javascript


输出
15

时间复杂度: O(N)
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程