Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Interview Problems on Queue
  • Practice Queue
  • MCQs on Queue
  • Queue Tutorial
  • Operations
  • Applications
  • Implementation
  • Stack vs Queue
  • Types of Queue
  • Circular Queue
  • Deque
  • Priority Queue
  • Stack using Queue
  • Advantages & Disadvantages
Open In App
Next Article:
String Guide for Competitive Programming
Next article icon

Heap Data Structure for Competitive Programming

Last Updated : 10 Mar, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Competitive programming needs smart tools to solve problems quickly. One key tool is the Heap Data Structure, which helps organize data in a way that's super fast. In this article, we'll break down the Heap, looking at its types, basic moves, and how it's a big deal in competitive programming. We'll focus on something called Priority Queue, a special use of Heap, and show you how to use it to solve problems better. It does not matter if you are new to Heap or if you have a little knowledge already, learning it will greatly enhance your problem-solving skills in competitive programming.

Table of Content

  • Introduction to Heap Data Structure
  • Types of Heap Data Structure
  • Operations of Heap Data Structure
  • What is Priority Queue?
  • Priority Queue in C++ for Competitve Programming
  • Priority Queue in Java for Competitve Programming
  • Priority Queue in Python for Competitve Programming
  • Problem Identification of Priority Queue
  • Priority Queue Use Cases in Competitive Programming
  • Practice Problems of Heap Data Structure for Competitive Programming

Introduction to Heap Data Structure:

A Heap is a specialized tree-based data structure that satisfies the heap property. In simple terms, it's a way of organizing elements in a hierarchy, where each element has a priority relative to others. In a Heap, the top element is always the one with the highest (or lowest) priority, making it quick to access. There are different types of heaps, but they all share this fundamental idea of efficient data organization.

Note: A Heap is a specialized tree-based data structure that satisfies the heap property. It can be implemented as an array.

Types of Heap Data Structure:

Generally, Heaps can be of two types:

  1. Max-Heap: In a Max-Heap the key present at the root node must be greatest among the keys present at all of its children. The same property must be recursively true for all sub-trees in that Binary Tree.
  2. Min-Heap: In a Min-Heap the key present at the root node must be minimum among the keys present at all of its children. The same property must be recursively true for all sub-trees in that Binary Tree.

Operations of Heap Data Structure:

The Heap Data Structure supports fundamental operations that enable efficient management of its elements. Below are some operations of Heap Data Structure:

1. Heapify:

  • It is the process to rearrange the elements to maintain the property of heap data structure.
  • It takes O(log N) to balance the tree. 

2. Insertion:

  • If we insert a new element into the heap since we are adding a new element into the heap so it will distort the properties of the heap so we need to perform the heapify operation so that it maintains the property of the heap.
  • This operation also takes O(logN) time.

3. getMax (For max-heap) or getMin (For min-heap):

  • It finds the maximum element or minimum element for max-heap and min-heap respectively and as we know minimum and maximum elements will always be the root node itself for min-heap and max-heap respectively.
  • It takes O(1) time.

4. removeMin or removeMax:

  • This operation returns and deletes the maximum element and minimum element from the max-heap and min-heap respectively. In short, it deletes the root element of the heap binary tree.
  • It takes O(1) time.

What is Priority Queue?

A Priority Queue is an abstract data type that stores elements along with their associated priorities, and it allows for efficient retrieval of the element with the highest (or lowest) priority. In simpler terms, a priority queue is a data structure that manages a collection of elements, each assigned a priority, and provides operations to insert elements and remove the element with the highest (or lowest) priority.

Key Characteristics of a Priority Queue:

  • Priority-Based Ordering: Elements in a priority queue are arranged based on their priority, not in the order of their insertion.
  • Efficient Access: The primary purpose of a priority queue is to quickly access and remove the element with the highest (max priority) or lowest (min priority) value.
  • Abstract Data Type: The priority queue abstracts away the specific details of how priorities are assigned or how the elements are stored internally.
  • Implementation: Priority queues can be implemented using various data structures, with heaps being a common choice due to their efficiency in maintaining priorities.

Common Operations on a Priority Queue:

  • Insertion (Push): Add an element to the priority queue with its associated priority.
  • Deletion (Pop): Remove the element with the highest (max priority) or lowest (min priority) value.
  • Peek (Top): Access the element with the highest (max priority) or lowest (min priority) value without removing it.

Priority Queue in C++ for Competitve Programming:

The priority_queue container from the C++ Standard Template Library (STL) provides a convenient way to work with priority queues. Below is a simple guide on using priority_queue in C++ for competitive programming:

Import Necessary Package:

import java.util.PriorityQueue;

Below are the Initialization and methods of Priority Queue in C++:

Initialization and MethodsInitialization Max Heap (default)Initialization Min Heap (default)
Initializationstd::priority_queue<int> maxHeap;std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;
Inserting ElementsmaxHeap.push(5);minHeap.push(5);
Removing Top ElementmaxHeap.pop();minHeap.pop();
Accessing Top Elementint topElement = maxHeap.top();int topElement = minHeap.top();
Size and Empty Checkint size = maxHeap.size();<br>bool isEmpty = maxHeap.empty();int size = minHeap.size();<br>bool isEmpty = minHeap.empty();

Custom Comparator in Priority Queue in C++ STL:

Priority Queue can also be used to store pairs inside of it and we can use custom comparators for ordering by first and second element. Refer to the below articles:

  • Custom Comparator in Priority_queue in C++ STL
  • Priority queue of pairs in C++ with ordering by first and second element

Priority Queue in Java for Competitve Programming:

In Java, the PriorityQueue class from the java.util package provides a convenient way to implement a Priority Queue for competitive programming. Here's a guide on using PriorityQueue in Java:

Import Necessary Package:

import java.util.PriorityQueue;

Below are the Initialization and methods of PriorityQueue in Java:

Initialization and MethodsInitialization Max Heap (default)Initialization Min Heap
InitializationPriorityQueue<Integer> maxHeap = new PriorityQueue<>();PriorityQueue<Integer> minHeap = new PriorityQueue<>(Comparator.naturalOrder());
Inserting ElementsmaxHeap.add(5);minHeap.add(5);
Accessing Top Elementint topElement = maxHeap.peek();int topElement = minHeap.peek();
Removing Top ElementmaxHeap.poll();minHeap.poll();
Size and Empty Checkint size = maxHeap.size();<br>boolean isEmpty = maxHeap.isEmpty();int size = minHeap.size();<br>boolean isEmpty = minHeap.isEmpty();

Custom Comparator in Priority Queue in Java :

We can use a custom comparator to implement a priority queue with specific ordering rules.

  • Implement PriorityQueue through Comparator in Java

Priority Queue in Python for Competitve Programming:

In Python, you can use the heapq module to implement a Priority Queue efficiently. Below is a guide on using heapq in Python for competitive programming:

Import Necessary Module:

import heapq

Below are the Initialization and methods of Priority Queue in Python:

Initialization and MethodsInitialization Min Heap (default)Initialization Max Heap (using negation)
Initializationmin_heap = []max_heap = []
Inserting Elementsheapq.heappush(min_heap, 5)heapq.heappush(max_heap, -5)
Accessing Top Elementtop_element_min = min_heap[0]top_element_max = -max_heap[0] # Remember to negate values for max heap
Removing Top Elementheapq.heappop(min_heap)heapq.heappop(max_heap)
Size and Empty Checksize_min = len(min_heap)
isEmpty_min = not bool(min_heap)
size_max = len(max_heap)
isEmpty_max = not bool(max_heap)

Problem Identification of Priority Queue:

Below are the few problems that will help to identify how or when can we use Priority Queue in competitive programming problem:

Problem 1: Given n energy drinks with values ai​ on a line, where drinking the ith drink ai​ increases stamina by ai​ if is positive, and decreases if ai is negative, and leaving the drink as it is does not affect our stamina. Starting with 0 stamina, determine the maximum number of drinks you can consume without stamina becoming negative at any point, and drinks must be consumed in order.

The problem can be solved in the following way:

  • Sequential Consumption:
    • Consume energy drinks one by one, moving from the leftmost to the rightmost drink.
  • Maintain Count:
    • Keep a running count of the number of drinks consumed.
  • Check Stamina:
    • After consuming each drink, assess whether the stamina becomes negative.
  • Remove Most Negative Drink:
    • If negative stamina occurs, identify the most negatively impactful drink taken so far.
    • Utilize a priority queue to efficiently find and remove the drink with the greatest negative impact on stamina.
  • Track Maximum Drinks:
    • Continuously track the maximum number of drinks consumed without stamina becoming negative.

Below is the implementation of above approach:

C++
#include <bits/stdc++.h> using namespace std;  // Function to solve the given problem int maxDrinksWithoutNegativeStamina(vector<int>& arr) {     long long currentSum = 0; // Current cumulative stamina      int drinksConsumed = 0; // Count of drinks consumed      priority_queue<int>         negativeElements; // Priority queue for efficiently                         // removing negative elements      // Iterate through the energy drinks     for (int i = 0; i < arr.size(); i++) {         // Current energy value of the drink         int currentElement = arr[i];         // Update cumulative stamina         currentSum += currentElement;          // Increment drinks consumed         drinksConsumed++;         // Add negative of the curren element to the         // priority queue         negativeElements.push(-currentElement);          // Check and remove elements causing negative         // stamina         while (currentSum < 0) {             // Reduce drinks consumed count             drinksConsumed--;                      // Add the most negatively impactful drink             currentSum += negativeElements.top();                      // Remove the drink from the priority queue             negativeElements.pop();         }     }      // Return the maximum number of drinks consumed without     // stamina becoming negative     return drinksConsumed; }  // Driver Code  int main() {      vector<int> energyDrinks = { 2, -3, 5, -1, 6 };     int result         = maxDrinksWithoutNegativeStamina(energyDrinks);     cout << "Maximum number of drinks without negative "             "stamina: "         << result << endl;      return 0; } 
Java
import java.util.PriorityQueue;  public class MaxDrinksWithoutNegativeStamina {      public static int maxDrinksWithoutNegativeStamina(int[] arr) {         int currentSum = 0;  // Current cumulative stamina         int drinksConsumed = 0;  // Count of drinks consumed          PriorityQueue<Integer> negativeElements = new PriorityQueue<>();  // Min heap for efficiently removing negative elements          // Iterate through the energy drinks         for (int currentElement : arr) {             // Update cumulative stamina             currentSum += currentElement;              // Increment drinks consumed             drinksConsumed++;              // Add the negative of the current element to the priority queue             negativeElements.add(-currentElement);              // Check and remove elements causing negative stamina             while (currentSum < 0) {                 // Reduce drinks consumed count                 drinksConsumed--;                  // Add the most negatively impactful drink                 currentSum += -negativeElements.poll();             }         }          // Return the maximum number of drinks consumed without stamina becoming negative         return drinksConsumed;     }      public static void main(String[] args) {         int[] energyDrinks = {2, -3, 5, -1, 6};         int result = maxDrinksWithoutNegativeStamina(energyDrinks);         System.out.println("Maximum number of drinks without negative stamina: " + result);     } }    // This code is contributed by shivamgupta0987654321 
C#
using System; using System.Collections.Generic;  class Program {     // Function to solve the given problem     static int MaxDrinksWithoutNegativeStamina(List<int> arr)     {         long currentSum = 0; // Current cumulative stamina          int drinksConsumed = 0; // Count of drinks consumed          PriorityQueue<int> negativeElements =           new PriorityQueue<int>(Comparer<int>.Create((a, b) => b.CompareTo(a)));         // Priority queue for efficiently removing negative elements          // Iterate through the energy drinks         for (int i = 0; i < arr.Count; i++)         {             // Current energy value of the drink             int currentElement = arr[i];             // Update cumulative stamina             currentSum += currentElement;              // Increment drinks consumed             drinksConsumed++;             // Add negative of the current element to the             // priority queue             negativeElements.Enqueue(-currentElement);              // Check and remove elements causing negative             // stamina             while (currentSum < 0)             {                 // Reduce drinks consumed count                 drinksConsumed--;                  // Add the most negatively impactful drink                 currentSum += negativeElements.Dequeue();             }         }          // Return the maximum number of drinks consumed without         // stamina becoming negative         return drinksConsumed;     }      // Driver Code     static void Main()     {         List<int> energyDrinks = new List<int> { 2, -3, 5, -1, 6 };         int result = MaxDrinksWithoutNegativeStamina(energyDrinks);         Console.WriteLine($"Maximum number of drinks without negative stamina: {result}");          Console.ReadLine();     } }  // Priority Queue Implementation public class PriorityQueue<T> {     private List<T> heap;     private readonly IComparer<T> comparer;      public PriorityQueue() : this(null) { }      public PriorityQueue(IComparer<T> comparer) : this(16, comparer) { }      public PriorityQueue(int capacity, IComparer<T> comparer)     {         this.heap = new List<T>(capacity);         this.comparer = comparer ?? Comparer<T>.Default;     }      public void Enqueue(T item)     {         heap.Add(item);         int i = heap.Count - 1;         while (i > 0)         {             int parent = (i - 1) / 2;             if (comparer.Compare(heap[parent], heap[i]) <= 0)                 break;              Swap(i, parent);             i = parent;         }     }      public T Dequeue()     {         int count = heap.Count - 1;         T root = heap[0];         heap[0] = heap[count];         heap.RemoveAt(count);          count--;         int i = 0;         while (true)         {             int left = i * 2 + 1;             if (left > count)                 break;              int right = left + 1;             if (right <= count && comparer.Compare(heap[right], heap[left]) < 0)                 left = right;              if (comparer.Compare(heap[left], heap[i]) >= 0)                 break;              Swap(i, left);             i = left;         }         return root;     }      public T Peek()     {         return heap[0];     }      public int Count     {         get { return heap.Count; }     }      private void Swap(int i, int j)     {         T tmp = heap[i];         heap[i] = heap[j];         heap[j] = tmp;     } } //THis code is contributed by Adarsh 
JavaScript
// Function to solve the given problem function maxDrinksWithoutNegativeStamina(arr) {     let currentSum = 0; // Current cumulative stamina     let drinksConsumed = 0; // Count of drinks consumed     const negativeElements = []; // Array to store negative elements      // Iterate through the energy drinks     for (let i = 0; i < arr.length; i++) {         // Current energy value of the drink         const currentElement = arr[i];         // Update cumulative stamina         currentSum += currentElement;         // Increment drinks consumed         drinksConsumed++;         // Add negative of the current element to the array         negativeElements.push(-currentElement);          // Check and remove elements causing negative stamina         while (currentSum < 0) {             // Reduce drinks consumed count             drinksConsumed--;             // Add the most negatively impactful drink             currentSum += negativeElements.pop();         }     }      // Return the maximum number of drinks consumed without stamina becoming negative     return drinksConsumed; }  // Driver code const energyDrinks = [2, -3, 5, -1, 6]; const result = maxDrinksWithoutNegativeStamina(energyDrinks); console.log("Maximum number of drinks without negative stamina: ", result); 
Python3
import heapq  def max_drinks_without_negative_stamina(arr):     current_sum = 0  # Current cumulative stamina     drinks_consumed = 0  # Count of drinks consumed      negative_elements = []  # Min heap for efficiently removing negative elements      # Iterate through the energy drinks     for current_element in arr:         # Update cumulative stamina         current_sum += current_element          # Increment drinks consumed         drinks_consumed += 1          # Add the negative of the current element to the priority queue         heapq.heappush(negative_elements, -current_element)          # Check and remove elements causing negative stamina         while current_sum < 0:             # Reduce drinks consumed count             drinks_consumed -= 1              # Add the most negatively impactful drink             current_sum += -heapq.heappop(negative_elements)      # Return the maximum number of drinks consumed without stamina becoming negative     return drinks_consumed  # Driver Code energy_drinks = [2, -3, 5, -1, 6] result = max_drinks_without_negative_stamina(energy_drinks) print(f"Maximum number of drinks without negative stamina: {result}") 

Output
Maximum number of drinks without negative stamina: 4

Problem 2: Given an array of n integers a1, a2,... an and a integer k. You can perform the following operation any number of times: Choose an index i within the range 1<=i<=n and set ai to -ai​. The task is to the value a1+ a2+...+ak minimum among all non-empty prefix sums of array a.

​The problem can be solved in the following way:

  • Greedy Approach:
    • Utilize a greedy strategy to solve the problem.
  • Independent Cases:
    • Address the problem in two independent cases.
  • Case 1: Iterate from k to 1:
    • For each index from k to 1, check if the prefix sum of i is less than the prefix sum of k.
    • If true, apply the operation on the maximal element in the segment [i+1, k]. Since performing an operation to any element in the segment [1,x] does nothing on prefix sum of i and k.
  • Case 2: Iterate from k+1 to n:
    • For each index from k+1 to n, check if the prefix sum of i is less than the prefix sum of k.
    • If true, apply the operation on the minimal element in the segment [k+1, i]. Since performing an operation to any element in the segment [i+1,n] does nothing on prefix sum of i and k.

Below is the implementation of above approach:

C++
#include <bits/stdc++.h> using namespace std;   // Function to solve the given problem void solve(vector<int> a, int n, int k) {     vector<int> b(n + 1); // Array to store cumulative prefix sums     int ans = 0; // Variable to store the final answer     int x = 0, y = 0, z = 1e18; // Temporary variables for calculations      priority_queue<int, vector<int>, greater<int>> pq; // Min heap for Case 2     priority_queue<int> pq2; // Max heap for Case 1      // Calculate cumulative prefix sums     for (int i = 1; i <= n; i++) {         b[i] += b[i - 1] + a[i-1];     }      // Case 1: Iterate from k to 1     for (int i = k; i > 0; i--) {         // Check if the prefix sum of i is less than the prefix sum of k         while (b[i] < b[k]) {         // Increment answer             ans++;                   // Get the maximal element in the segment [i+1, k]             int m = pq2.top();                   // Update prefix sum             b[k] = b[k] - 2 * m;              pq2.pop(); // Remove the maximal element from the priority queue         }         pq2.push(a[i-1]); // Add the current element to the max heap     }      // Case 2: Iterate from k+1 to n     for (int i = k + 1; i <= n; i++) {         y = y + a[i-1];         pq.push(a[i-1]);         // Check if the prefix sum of i is less than the prefix sum of k         while (y < 0) {         // Get the minimal element in the segment [k+1, i]             int m = pq.top();                   // Update prefix sum             y = y - 2 * m;                   // Increment answer             ans++;                   // Remove the minimal element from the priority queue             pq.pop();          }     }      cout << ans << "\n"; // Output the final answer }  int main() {     // Example usage     vector<int> array = {3, -2, 5, -1, -4};     int n = array.size();     int k = 3;     solve(array, n, k);      return 0; } 
Java
import java.util.*;  public class Main {     // Function to solve the given problem     static void solve(ArrayList<Integer> a, int n, int k) {         ArrayList<Integer> b = new ArrayList<>(Collections.nCopies(n + 1, 0));  // Array to store cumulative prefix sums         int ans = 0;  // Variable to store the final answer         int x = 0, y = 0, z = (int) 1e18;  // Temporary variables for calculations          PriorityQueue<Integer> pq = new PriorityQueue<>();  // Min heap for Case 2         PriorityQueue<Integer> pq2 = new PriorityQueue<>(Collections.reverseOrder());  // Max heap for Case 1          // Calculate cumulative prefix sums         for (int i = 1; i <= n; i++) {             b.set(i, b.get(i - 1) + a.get(i - 1));         }          // Case 1: Iterate from k to 1         for (int i = k; i > 0; i--) {             // Check if the prefix sum of i is less than the prefix sum of k             while (b.get(i) < b.get(k)) {                 ans++;                  // Get the maximal element in the segment [i+1, k]                 int m = pq2.poll();                  // Update prefix sum                 b.set(k, b.get(k) - 2 * m);             }             pq2.add(a.get(i - 1));  // Add the current element to the max heap         }          // Case 2: Iterate from k+1 to n         for (int i = k + 1; i <= n; i++) {             y = y + a.get(i - 1);             pq.add(a.get(i - 1));             // Check if the prefix sum of i is less than the prefix sum of k             while (y < 0) {                 // Get the minimal element in the segment [k+1, i]                 int m = pq.poll();                  // Update prefix sum                 y = y - 2 * m;                  ans++;                  // Remove the minimal element from the priority queue             }         }          System.out.println(ans);       }      public static void main(String[] args) {         ArrayList<Integer> array = new ArrayList<>(Arrays.asList(3, -2, 5, -1, -4));         int n = array.size();         int k = 3;         solve(array, n, k);     } } 
C#
using System; using System.Collections.Generic;  class Program {     // Function to solve the given problem     static void Solve(List<int> a, int n, int k)     {         List<int> b = new List<int>(             new int[n + 1]); // List to store cumulative                              // prefix sums         int ans = 0; // Variable to store the final answer         int y = 0; // Temporary variable for calculations          PriorityQueue<int> pq             = new PriorityQueue<int>(); // Min heap for Case                                         // 2         PriorityQueue<int> pq2 = new PriorityQueue<int>(             (p, q) => q.CompareTo(p)); // Max heap for Case 1          // Calculate cumulative prefix sums         for (int i = 1; i <= n; i++) {             b[i] = b[i - 1] + a[i - 1];         }          // Case 1: Iterate from k to 1         for (int i = k; i > 0; i--) {             // Check if the prefix sum of i is less than the             // prefix sum of k             while (b[i] < b[k]) {                 ans++;                  // Get the maximal element in the segment                 // [i+1, k]                 int m = pq2.Peek();                  // Update prefix sum                 b[k] = b[k] - 2 * m;                 pq2.Pop(); // Remove the maximal element                            // from the priority queue             }             pq2.Push(a[i - 1]); // Add the current element                                 // to the max heap         }          // Case 2: Iterate from k+1 to n         for (int i = k + 1; i <= n; i++) {             y = y + a[i - 1];             pq.Push(a[i - 1]);             // Check if the prefix sum of i is less than the             // prefix sum of k             while (y < 0) {                 // Get the minimal element in the segment                 // [k+1, i]                 int m = pq.Peek();                  // Update prefix sum                 y = y - 2 * m;                  ans++;                  // Remove the minimal element from the                 // priority queue                 pq.Pop();             }         }          Console.WriteLine(ans);     }      static void Main(string[] args)     {         // Example usage         List<int> array = new List<int>{ 3, -2, 5, -1, -4 };         int n = array.Count;         int k = 3;         Solve(array, n, k);     } }  // Priority Queue Implementation public class PriorityQueue<T> {     private List<T> data;     private readonly Comparison<T> comparison;      public PriorityQueue() { data = new List<T>(); }      public PriorityQueue(Comparison<T> comparison)         : this()     {         this.comparison = comparison;     }      public void Push(T item)     {         data.Add(item);         int ci = data.Count - 1;         while (ci > 0) {             int pi = (ci - 1) / 2;             if (Compare(data[ci], data[pi]) >= 0)                 break;             T tmp = data[ci];             data[ci] = data[pi];             data[pi] = tmp;             ci = pi;         }     }      public T Peek()     {         if (data.Count == 0)             throw new InvalidOperationException(                 "Queue empty");         return data[0];     }      public T Pop()     {         if (data.Count == 0)             throw new InvalidOperationException(                 "Queue empty");         T pop = data[0];         data[0] = data[data.Count - 1];         data.RemoveAt(data.Count - 1);          int ci = 0;         while (ci < data.Count) {             int lci = 2 * ci + 1;             int rci = 2 * ci + 2;             if (lci >= data.Count)                 break;             int mini = lci;             if (rci < data.Count                 && Compare(data[rci], data[lci]) < 0)                 mini = rci;             if (Compare(data[ci], data[mini]) <= 0)                 break;             T tmp = data[ci];             data[ci] = data[mini];             data[mini] = tmp;             ci = mini;         }          return pop;     }      public int Count     {         get { return data.Count; }     }      private int Compare(T i, T j)     {         if (comparison != null)             return comparison(i, j);         return Comparer<T>.Default.Compare(i, j);     } } 
JavaScript
function solve(a, n, k) {   let b = Array(n + 1).fill(0);  // Array to store cumulative prefix sums   let ans = 0;  // Variable to store the final answer   let x = 0, y = 0, z = 1e18;  // Temporary variables for calculations    let pq = [];  // Min heap for Case 2   let pq2 = [];  // Max heap for Case 1    // Calculate cumulative prefix sums   for (let i = 1; i <= n; i++) {     b[i] = b[i - 1] + a[i - 1];   }    // Case 1: Iterate from k to 1   for (let i = k; i > 0; i--) {     // Check if the prefix sum of i is less than the prefix sum of k     while (b[i] < b[k]) {       ans += 1;        // Get the maximal element in the segment [i+1, k]       let m = pq2.pop();        // Update prefix sum       b[k] = b[k] - 2 * m;     }      pq2.push(a[i - 1]);  // Add the current element to the max heap   }    // Case 2: Iterate from k+1 to n   for (let i = k + 1; i <= n; i++) {     y = y + a[i - 1];     pq.push(a[i - 1]);      // Check if the prefix sum of i is less than the prefix sum of k     while (y < 0) {       // Get the minimal element in the segment [k+1, i]       let m = pq.pop();        // Update prefix sum       y = y - 2 * m;        ans += 1;     }   }    console.log(ans);  // Output the final answer }  let array = [3, -2, 5, -1, -4]; let n = array.length; let k = 3; solve(array, n, k); 
Python3
import heapq  def solve(a, n, k):     b = [0] * (n + 1)  # Array to store cumulative prefix sums     ans = 0  # Variable to store the final answer     x, y, z = 0, 0, 1e18  # Temporary variables for calculations      pq = []  # Min heap for Case 2     pq2 = []  # Max heap for Case 1      # Calculate cumulative prefix sums     for i in range(1, n + 1):         b[i] = b[i - 1] + a[i - 1]      # Case 1: Iterate from k to 1     for i in range(k, 0, -1):         # Check if the prefix sum of i is less than the prefix sum of k         while b[i] < b[k]:             # Increment answer             ans += 1              # Get the maximal element in the segment [i+1, k]             m = heapq.heappop(pq2)              # Update prefix sum             b[k] = b[k] - 2 * m          heapq.heappush(pq2, a[i - 1])  # Add the current element to the max heap      # Case 2: Iterate from k+1 to n     for i in range(k + 1, n + 1):         y = y + a[i - 1]         heapq.heappush(pq, a[i - 1])          # Check if the prefix sum of i is less than the prefix sum of k         while y < 0:             # Get the minimal element in the segment [k+1, i]             m = heapq.heappop(pq)              # Update prefix sum             y = y - 2 * m              # Increment answer             ans += 1      print(ans)  # Output the final answer  # Example usage array = [3, -2, 5, -1, -4] n = len(array) k = 3 solve(array, n, k) 

Output
3

Priority Queue Use Cases in Competitive Programming:

Here are some common use cases for priority queues in competitive programming:

1. Dijkstra's Algorithm:

Priority queues are commonly employed to implement Dijkstra's algorithm for finding the shortest paths in a graph. The priority queue efficiently selects the vertex with the smallest distance at each step. It is also used in solving problems which are variation of Dijkstra's Algorithm

2. Prim's Algorithm:

Similar to Dijkstra's, priority queues play a crucial role in implementing Prim's algorithm for finding the minimum spanning tree in a weighted graph. The priority queue helps choose the edge with the smallest weight at each iteration.

3. Median Maintenance:

Heaps can be employed to efficiently find the median of a stream of numbers, a common problem in competitive programming. By maintaining two heaps (a max heap and a min heap), the median can be efficiently updated as new elements are added.

4. Kth Largest/Smallest Element:

Priority queues help find the Kth largest or smallest element efficiently in an array or stream of numbers. For example, a max heap can be used to find the Kth largest element, while a min heap can find the Kth smallest element.

5. Huffman Coding:

Priority queues are crucial in Huffman coding, a widely used algorithm for data compression. The algorithm builds a variable-length prefix coding tree, and a priority queue helps in efficiently merging nodes based on their frequencies.

6. Task Scheduling:

Competitive programming problems often involve scheduling tasks based on their priority or execution time. A priority queue helps efficiently manage and execute tasks in the order of their priority.

Practice Problems of Heap Data Structure for Competitive Programming:

Here are some practice problems involving heap data structures that you can use to enhance your skills in competitive programming:

Problem

Minimum characters required to be removed to make frequency of each character unique

Minimize the sum calculated by repeatedly removing any two elements and inserting their sum to the Array

Maximum score possible from an array with jumps of at most length K

Length of Smallest Subsequence such that sum of elements is greater than equal to K

Minimize Sum of an Array by at most K reductions

Maximize product of sum of speeds of K workers and their minimum efficiency

Maximum possible sub-array sum after at most X swaps

Maximize the profit after selling the tickets

Minimum increment/decrement to make array non-Increasing

Minimum cost path from source node to destination node via K intermediate nodes


Next Article
String Guide for Competitive Programming

M

mridul_gfg
Improve
Article Tags :
  • Heap
  • Competitive Programming
  • DSA
  • priority-queue
Practice Tags :
  • Heap
  • priority-queue

Similar Reads

  • DP on Trees for Competitive Programming
    Dynamic Programming (DP) on trees is a powerful algorithmic technique commonly used in competitive programming. It involves solving various tree-related problems by efficiently calculating and storing intermediate results to optimize time complexity. By using the tree structure, DP on trees allows p
    15+ min read
  • Queue for Competitive Programming
    In competitive programming, a queue is a data structure that is often used to solve problems that involve tasks that need to be completed in a specific order. This article explores the queue data structure and identifies its role as a critical tool for overcoming coding challenges in competitive pro
    8 min read
  • Stack for Competitive Programming
    For competitive programming to be successful, efficient data structures and algorithms are essential. The stack is one such tool. In this article, we will examine how stack data structures play an important role in solving problems efficiently during competitive programming challenges. We will explo
    7 min read
  • String Guide for Competitive Programming
    Strings are a sequence of characters, and are one of the most fundamental data structures in Competitive Programming. String problems are very common in competitive programming contests, and can range from simple to very challenging. In this article we are going to discuss about most frequent string
    15 min read
  • Top 10 Algorithms and Data Structures for Competitive Programming
    In this post, we will discuss Important top 10 algorithms and data structures for competitive coding. Topics : Graph algorithmsDynamic programmingSearching and Sorting:Number theory and Other MathematicalGeometrical and Network Flow AlgorithmsData StructuresThe links below cover most important algor
    3 min read
  • Segment Trees for Competitive Programming
    Segment Tree is one of the most important data structures used for solving problems based on range queries and updates. Problems based on Segment Trees are very common in Programming Contests. This article covers all the necessary concepts required to have a clear understanding of Segment Trees. Tab
    8 min read
  • Fast I/O for Competitive Programming
    In competitive programming, it is important to read input as fast as possible so we save valuable time. You must have seen various problem statements saying: " Warning: Large I/O data, be careful with certain languages (though most should be OK if the algorithm is well designed)" . The key for such
    4 min read
  • How to Get Started with Competitive Programming?
    If you're a Computer Science student or a coding enthusiast, chances are more you've heard individuals discussing their Competitive Programming skills and rankings & achievements in various coding challenges or contests. And truly, Competitive Programming skills are one of those few skills that
    8 min read
  • Precomputation Techniques for Competitive Programming
    What is the Pre-Computation Technique?Precomputation refers to the process of pre-calculating and storing the results of certain computations or data structures in advance, in order to speed up the execution time of a program. This can be useful in situations where the same calculations or data stru
    15+ min read
  • Why Should You Do Competitive Programming?
    Competitive programming is a mind sport, where people compete against each other to solve some programming questions/logic with an efficient approach and within a time constraint. The goal of competitive programming is to write code to solve a problem within a given timeframe. There are mainly mathe
    8 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences