Open In App

CSES Solutions – Towers

Last Updated : 28 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

You are given N cubes as an array cubes[] in a certain order, and your task is to build towers using them. Whenever two cubes are one on top of the other, the upper cube must be smaller than the lower cube. You must process the cubes in the given order. You can always either place the cube on top of an existing tower or begin a new tower. What is the minimum possible number of towers?

Examples:

Input: N = 5, cubes[] = {3, 8, 2, 1, 5}
Output: 2
Explanation: We can make 2 towers {3, 2, 1} and {8, 5}.

Input: N = 4, cubes[] = {4, 3, 1, 2}
Output: 2
Explanation: We can make 2 towers {4, 3, 1} and {2}.

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

We can solve the problem by iterating over the cubes and for every cube, we will find the smallest cube which is larger than the current cube and is placed on the top of any tower. This can be done by storing only the top elements of the tower in a multiset. So, for every block we find the tower that has the topmost block just greater than the current block. This can be easily found using Binary Search upper bound on multiset. Also, whenever we add a block to a tower, we need to update the top of the tower as well.

Step-by-step algorithm:

  • Maintain a variable, say ans to store the number of towers needed.
  • Maintain a multiset, say topElements store the topmost cubes of all towers.
  • For each cube with size cubes[i], find the smallest cube which has size > cubes[i] and is among the top-most cubes of towers.
    • If there is no cube among the top-most cubes which has size > cubes[i], then we have to make another tower.
    • Otherwise, if there is a cube among the top-most cubes which has size > cubes[i], then we place the current cube on top of it.
  • After all the iterations, return ans as the final answer.

Below is the implementation of the algorithm:

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

// function to find the minimum number of towers
ll solve(ll N, vector<ll>& cubes)
{
    // Variable to store the number of twers
    ll ans = 0;

    // Multiset to store the size of top most cubes of all
    // towers
    multiset<ll> topElements;
    for (int i = 0; i < N; i++) {
        // Find the smallest cube which is larger than
        // cubes[i]
        auto it = topElements.upper_bound(cubes[i]);
        // If no cube has size > cubes[i], then we need
        // another tower for this block
        if (it == topElements.end()) {
            ans++;
            topElements.insert(cubes[i]);
        }
        // If there is a cube which has size > cubes[i],
        // place cubes[i] on top of it.
        else {
            topElements.erase(it);
            topElements.insert(cubes[i]);
        }
    }
    return ans;
}

int main()
{
    // Sample Input
    ll N = 5;
    vector<ll> cubes = { 3, 8, 2, 1, 5 };

    cout << solve(N, cubes);
}
Java
import java.util.*;

public class Main {

    // function to find the minimum number of towers
    static long solve(long N, ArrayList<Long> cubes) {
        // Variable to store the number of towers
        long ans = 0;

        // Multiset to store the size of top most cubes of all towers
        TreeSet<Long> topElements = new TreeSet<>();
        for (int i = 0; i < N; i++) {
            // Find the smallest cube which is larger than cubes[i]
            Long it = topElements.higher(cubes.get(i));
            // If no cube has size > cubes[i], then we need another tower for this block
            if (it == null) {
                ans++;
                topElements.add(cubes.get(i));
            }
            // If there is a cube which has size > cubes[i], place cubes[i] on top of it.
            else {
                topElements.remove(it);
                topElements.add(cubes.get(i));
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        // Sample Input
        long N = 5;
        ArrayList<Long> cubes = new ArrayList<>(Arrays.asList(3L, 8L, 2L, 1L, 5L));

        System.out.println(solve(N, cubes));
    }
}
C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    public static long Solve(long N, List<long> cubes)
    {
        long ans = 0;

        // List to simulate the behavior of a multiset for top elements of towers
        List<long> topElements = new List<long>();

        foreach (var cube in cubes)
        {
            // Find the index of the smallest cube which is larger than `cube`
            var index = topElements.FindIndex(x => x > cube);
            if (index == -1)
            {
                ans++;
                topElements.Add(cube); // If no such cube, add a new tower
            }
            else
            {
                topElements[index] = cube; // Replace the top cube of the found tower
            }
            topElements.Sort(); // Keep topElements sorted
        }

        return ans;
    }

    static void Main(string[] args)
    {
        long N = 5;
        List<long> cubes = new List<long> { 3, 8, 2, 1, 5 };

        Console.WriteLine(Solve(N, cubes));
    }
}
Javascript
function GFG(N, cubes) {
    // Variable to store the number of the towers
    let ans = 0;
    let topElements = new Set();
    for (let i = 0; i < N; i++) {
        // Find the smallest cube which is larger than cubes[i]
        let it = Array.from(topElements).findIndex(c => c > cubes[i]);
        if (it === -1) {
            ans++;
            topElements.add(cubes[i]);
        }
        // If there is a cube which has size > cubes[i]
        // place cubes[i] on top of it
        else {
            topElements.delete(cubes[it]);
            topElements.add(cubes[i]);
        }
    }
    return ans;
}
// Sample Input
let N = 5;
let cubes = [3, 8, 2, 1, 5];
console.log(GFG(N, cubes));
Python3
from bisect import bisect_right

# Function to find the minimum number of towers
def solve(N, cubes):
    # Variable to store the number of towers
    ans = 0

    # List to store the size of top most cubes of all towers
    top_elements = []

    for i in range(N):
        # Find the index of the smallest cube which is larger than cubes[i]
        index = bisect_right(top_elements, cubes[i])
        
        # If no cube has size > cubes[i], then we need another tower for this block
        if index == len(top_elements):
            ans += 1
            top_elements.append(cubes[i])
        # If there is a cube which has size > cubes[i], place cubes[i] on top of it.
        else:
            top_elements[index] = cubes[i]
            top_elements.sort()  # Sorting after replacing the cube ensures top_elements remains sorted
        
    return ans

def main():
    # Sample Input
    N = 5
    cubes = [3, 8, 2, 1, 5]

    print(solve(N, cubes))

if __name__ == "__main__":
    main()

Output
2

Time Complexity: O(N * logN), where N is the number of cubes.
Auxiliary Space: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads