Open In App

CSES Solutions – Traffic Lights

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

There is a street of length X whose positions are numbered 0,1 … X. Initially there are no traffic lights, but N sets of traffic lights are added to the street one after another denoted by P[]. Your task is to calculate the length of the longest passage without traffic lights after each addition.

Examples:

Input: X = 8, N = 3, P[] = {3, 6, 2}
Output: 5 3 3
Explanation: After the first traffic light is added at position 3, we have two passages: 0 to 3 and 3 to 8. So, the maximum length will be 8 – 3 = 5. After the second traffic light is added at position 6, we have three passages: 0 to 3, 3 to 6 and 6 to 8. So, the maximum length will be 6 – 3 = 3. After the third traffic light is added at position 2, we have 4 passages: 0 to 2, 2 to 3, 3 to 6 and 6 to 8. So, the maximum length of passage will be 6 – 3 = 3.

Input: X = 7, N = 2, P[] = {2, 3}
Output: 5 4
Explanation: After the first traffic light is added at position 2, we have two passages: 0 to 2 and 2 to 7. So, the maximum length will be 7 – 2 = 5. After the second traffic light is added at position 3, we have three passages: 0 to 2, 2 to 3 and 3 to 7. So, the maximum length will be 7 – 3 = 4.

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

The problem can be solved using set of pairs to store the starting and ending of all ranges and multiset to store the lengths of all ranges. Initially, we push the range (0, X) to the set and store the length X to the multiset. For every traffic light at position P, we find the range [L, R] in which position P lies and remove [L, R] and insert [L, P] and [P, R]. Also, we remove the length of range [L, R] from multiset and insert the lengths of [L, P] and [P, R]. We can find the length of longest passage from the multiset.

Step-by-step algorithm:

  • Declare a set ranges to store the starting and ending point of ranges.
  • Declare a multiset range_lengths to store the lengths of the ranges.
  • Iterate through all the points and find the range[L, R] in which the point at position X lies.
  • Break the ranges into two parts: L to X and X to R and push their lengths into the range lengths.
  • Also remove the range [L, R] from the set and its length from the multiset.
  • As multiset has elements sorted in ascending order, we can print the last element of the multiset as the answer.

Below is the implementation of the algorithm:

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

void solve(ll X, ll N, ll* P)
{
    // to store ranges
    set<pair<int, int> > ranges;
    ranges.insert({ 0, X });
    // to store range lengths
    multiset<ll> range_lengths;
    range_lengths.insert(X);

    for (int i = 0; i < N; i++) {
        ll pos = P[i];
        // find the range in which pos lies
        auto it = ranges.upper_bound({ pos, 0 });
        it--;

        ll start = it->first;
        ll end = it->second;

        // Remove range [start, end] from ranges
        ranges.erase(it);
        // Remove length of range [start, end] from the
        // range_lengths
        range_lengths.erase(
            range_lengths.find(end - start));

        // Insert the new ranges
        ranges.insert({ start, pos });
        ranges.insert({ pos, end });
        range_lengths.insert(pos - start);
        range_lengths.insert(end - pos);

        // Print the last element of multiset as the answer
        cout << *range_lengths.rbegin() << "\n";
    }
}

// Drive Code
int main()
{
    ll X = 8, N = 3, P[] = { 3, 6, 2 };
    solve(X, N, P);
    return 0;
}
Java
import java.util.TreeMap;
import java.util.TreeSet;

public class Main {

    public static void solve(long X, int N, long[] P)
    {
        // to store ranges
        TreeSet<Pair<Long, Long> > ranges = new TreeSet<>();
        ranges.add(new Pair<>(0L, X));
        // to store range lengths
        TreeMap<Long, Integer> range_lengths
            = new TreeMap<>();
        range_lengths.put(X, 1);

        for (int i = 0; i < N; i++) {
            long pos = P[i];
            // find the range in which pos lies
            Pair<Long, Long> it = ranges.floor(
                new Pair<>(pos, Long.MAX_VALUE));

            long start = it.first;
            long end = it.second;

            // Remove range [start, end] from ranges
            ranges.remove(it);
            // Remove length of range [start, end] from the
            // range_lengths
            int length = range_lengths.get(end - start);
            if (length == 1) {
                range_lengths.remove(end - start);
            }
            else {
                range_lengths.put(end - start, length - 1);
            }

            // Insert the new ranges
            ranges.add(new Pair<>(start, pos));
            ranges.add(new Pair<>(pos, end));
            range_lengths.put(
                pos - start,
                range_lengths.getOrDefault(pos - start, 0)
                    + 1);
            range_lengths.put(
                end - pos,
                range_lengths.getOrDefault(end - pos, 0)
                    + 1);

            // Print the last element of map as the answer
            System.out.println(range_lengths.lastKey());
        }
    }

    public static void main(String[] args)
    {
        long X = 8;
        int N = 3;
        long[] P = { 3, 6, 2 };
        solve(X, N, P);
    }

    static class Pair<K extends Comparable<K>, V
                          extends Comparable<V> >
        implements Comparable<Pair<K, V> > {
        K first;
        V second;

        public Pair(K first, V second)
        {
            this.first = first;
            this.second = second;
        }

        @Override public int compareTo(Pair<K, V> other)
        {
            int cmp = this.first.compareTo(other.first);
            if (cmp != 0)
                return cmp;
            return this.second.compareTo(other.second);
        }
    }
}
C#
using System;
using System.Collections.Generic;
using System.Linq;

public class RangeSolver
{
    public static void Solve(int X, int N, int[] P)
    {
        // to store ranges
        List<Tuple<int, int>> ranges = new List<Tuple<int, int>>();
        ranges.Add(Tuple.Create(0, X));
        // to store range lengths
        Dictionary<int, int> rangeLengths = new Dictionary<int, int>();
        rangeLengths[X] = 1;

        for (int i = 0; i < N; i++)
        {
            int pos = P[i];
            // find the range in which pos lies
            Tuple<int, int> it = null;
            foreach (var r in ranges)
            {
                if (r.Item1 <= pos && pos <= r.Item2)
                {
                    it = r;
                    break;
                }
            }

            Tuple<int, int> range = it ?? throw new InvalidOperationException("Range not found");

            int start = range.Item1;
            int end = range.Item2;

            // Remove range [start, end] from ranges
            ranges.Remove(range);
            // Remove length of range [start, end] from the rangeLengths
            int length = rangeLengths[end - start];
            if (length == 1)
            {
                rangeLengths.Remove(end - start);
            }
            else
            {
                rangeLengths[end - start] = length - 1;
            }

            // Insert the new ranges
            ranges.Add(Tuple.Create(start, pos));
            ranges.Add(Tuple.Create(pos, end));
            if (rangeLengths.ContainsKey(pos - start))
                rangeLengths[pos - start] += 1;
            else
                rangeLengths[pos - start] = 1;
            if (rangeLengths.ContainsKey(end - pos))
                rangeLengths[end - pos] += 1;
            else
                rangeLengths[end - pos] = 1;

            // Print the last element of map as the answer
            Console.WriteLine(rangeLengths.Keys.Max());
        }
    }

    // Drive Code
    public static void Main(string[] args)
    {
        int X = 8, N = 3;
        int[] P = { 3, 6, 2 };
        Solve(X, N, P);
    }
}
Javascript
function solve(X, N, P) {
    // Define a set to store ranges
    let ranges = new Set();
    ranges.add([0, X]);

    // Define a map to store range lengths
    let rangeLengths = new Map();
    rangeLengths.set(X, 1);

    for (let i = 0; i < N; i++) {
        let pos = P[i];
        // Find the range in which pos lies
        let it = Array.from(ranges).find(([start, end]) => pos >= start && pos < end);
        let [start, end] = it;

        // Remove range [start, end] from ranges
        ranges.delete(it);
        // Remove length of range [start, end] from the rangeLengths
        let length = end - start;
        let count = rangeLengths.get(length);
        if (count === 1) {
            rangeLengths.delete(length);
        } else {
            rangeLengths.set(length, count - 1);
        }

        // Insert the new ranges
        ranges.add([start, pos]);
        ranges.add([pos, end]);
        // Update rangeLengths
        let leftLength = pos - start;
        let rightLength = end - pos;
        rangeLengths.set(leftLength, (rangeLengths.get(leftLength) || 0) + 1);
        rangeLengths.set(rightLength, (rangeLengths.get(rightLength) || 0) + 1);

        // Print the last element of map as the answer
        console.log(Math.max(...Array.from(rangeLengths.keys())));
    }
}

// Main function
function main() {
    let X = 8;
    let N = 3;
    let P = [3, 6, 2];
    solve(X, N, P);
}

// Run the main function
main();
Python3
# Python program for the above approach
from collections import defaultdict

def solve(X, N, P):
    # to store ranges
    ranges = [(0, X)]
    # to store range lengths
    range_lengths = defaultdict(int)
    range_lengths[X] = 1

    for i in range(N):
        pos = P[i]
        # find the range in which pos lies
        it = None
        for r in ranges:
            if r[0] <= pos <= r[1]:
                it = r
                break

        start, end = it

        # Remove range [start, end] from ranges
        ranges.remove(it)
        # Remove length of range [start, end] from the range_lengths
        length = range_lengths[end - start]
        if length == 1:
            del range_lengths[end - start]
        else:
            range_lengths[end - start] = length - 1

        # Insert the new ranges
        ranges.append((start, pos))
        ranges.append((pos, end))
        range_lengths[pos - start] += 1
        range_lengths[end - pos] += 1

        # Print the last element of map as the answer
        print(max(range_lengths.keys()))

X = 8
N = 3
P = [3, 6, 2]
solve(X, N, P)

# This code is contributed by Susobhan Akhuli

Output
5
3
3


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



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

Similar Reads