CSES Solutions – Traffic Lights
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:
- 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
Time Complexity: O(N * logN), where N is the number of traffic lights.
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...