CSES Solutions Traffic Lights (original) (raw)

Last Updated : 22 Mar, 2024

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:

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 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

`

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