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