Lifeguards
Solución en video
Por Satvika Sridhar
Nota: La solución en video podría no ser la misma que las otras soluciones. Código en C++ y Java.
Video de YouTube (X2M-fuPtdlk)
Implementación 1 (con conjuntos)
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
struct Event {
int time;
int cow_id;
bool is_start;
};
bool operator<(const Event &a, const Event &b) { return a.time < b.time; }
int main() {
freopen("lifeguards.in", "r", stdin);
int n;
cin >> n;
vector<Event> events;
for (int i = 0; i < n; i++) {
int l, r;
cin >> l >> r;
// cada intervalo de vaca se puede representar con un evento de inicio y de fin
events.push_back({l, i, true});
events.push_back({r, i, false});
}
sort(events.begin(), events.end());
// cuánto tiempo pasa sola cada vaca
vector<int> alone_time(n);
// vacas que están trabajando ahora en [prev_time, curr_time]
set<int> active;
// tiempo del evento anterior
int prev_time = 0;
// cuánto tiempo cubren todas las vacas juntas
int total_time = 0;
for (const Event &e : events) {
int curr_time = e.time;
// 1. actualizamos el tiempo total cubierto por todas las vacas
if (active.size() > 0) { total_time += curr_time - prev_time; }
// 2. comprobamos si hay solo una vaca en [prev_time, curr_time]
if (active.size() == 1) {
alone_time[*active.begin()] += curr_time - prev_time;
}
// 3. procesamos el evento
if (e.is_start) {
active.insert(e.cow_id);
} else {
active.erase(e.cow_id);
}
// 4. actualizamos prev_time
prev_time = curr_time;
}
int min_alone_time = *min_element(alone_time.begin(), alone_time.end());
freopen("lifeguards.out", "w", stdout);
cout << total_time - min_alone_time << endl;
}Implementación 2 (sin conjuntos)
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
struct Cow {
int l, r;
};
bool operator<(const Cow &a, const Cow &b) { return a.l < b.l; }
int main() {
freopen("lifeguards.in", "r", stdin);
int n;
cin >> n;
vector<Cow> cows(n);
for (int i = 0; i < n; i++) { cin >> cows[i].l >> cows[i].r; }
sort(cows.begin(), cows.end());
int total_time = 0;
// right = punto de fin máximo de los salvavidas considerados hasta ahora
int left = 0, right = 0;
// calculamos total_time
for (int i = 0; i < n; i++) {
if (cows[i].r > right) {
left = max(right, cows[i].l);
total_time += cows[i].r - left;
right = cows[i].r;
}
}
Cow last;
last.l = cows[n - 1].r;
cows.push_back(last);
// tiempo mínimo que una vaca pasa sola
int min_alone_time = total_time;
right = 0;
for (int i = 0; i < n; i++) {
int curr_res = min(cows[i + 1].l, cows[i].r) - max(cows[i].l, right);
min_alone_time = min(min_alone_time, curr_res);
right = max(right, cows[i].r);
}
freopen("lifeguards.out", "w", stdout);
// si min_alone_time < 0 entonces la respuesta = tot
cout << total_time - max(min_alone_time, 0) << endl;
}Implementación
Complejidad temporal:
import java.io.*;
import java.util.*;
public class Lifeguards {
// BeginCodeSnip{Event Class}
static class Event implements Comparable<Event> {
public int time;
public int cowId;
public boolean isStart;
public Event(int time, int cowId, boolean isStart) {
this.time = time;
this.cowId = cowId;
this.isStart = isStart;
}
@Override
public int compareTo(Event other) {
return time - other.time;
}
}
// EndCodeSnip
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new FileReader("lifeguards.in"));
int n = Integer.parseInt(read.readLine());
Event[] events = new Event[2 * n];
for (int i = 0; i < n; i++) {
StringTokenizer e = new StringTokenizer(read.readLine());
int l = Integer.parseInt(e.nextToken());
int r = Integer.parseInt(e.nextToken());
events[2 * i] = new Event(l, i, true);
events[2 * i + 1] = new Event(r, i, false);
}
Arrays.sort(events);
// cuánto tiempo pasa sola cada vaca
int[] aloneTime = new int[n];
// vacas que están trabajando ahora en [prev_time, curr_time]
Set<Integer> active = new HashSet<>();
// tiempo del evento anterior
int prevTime = 0;
// cuánto tiempo cubren todas las vacas juntas
int totalTime = 0;
for (Event e : events) {
int currTime = e.time;
// 1. actualizamos el tiempo total cubierto por todas las vacas
if (active.size() > 0) { totalTime += currTime - prevTime; }
// 2. comprobamos si hay solo una vaca en [prevTime, currTime]
if (active.size() == 1) {
aloneTime[active.iterator().next()] += currTime - prevTime;
}
// 3. procesamos el evento
if (e.isStart) {
active.add(e.cowId);
} else {
active.remove(e.cowId);
}
// 4. actualizamos prevTime
prevTime = currTime;
}
int minAloneTime = Arrays.stream(aloneTime).min().getAsInt();
PrintWriter written = new PrintWriter("lifeguards.out");
written.println(totalTime - minAloneTime);
written.close();
}
}# BeginCodeSnip{Event Class}
class Event:
def __init__(self, time: int, cow_id: int, is_start: bool) -> None:
self.time = time
self.cow_id = cow_id
self.is_start = is_start
# EndCodeSnip
with open("lifeguards.in") as read:
n = int(read.readline())
events = []
for i in range(n):
l, r = [int(i) for i in read.readline().split()]
# cada intervalo de vaca se puede representar con un evento de inicio y de fin
events.append(Event(l, i, True))
events.append(Event(r, i, False))
events.sort(key=lambda e: e.time)
# cuánto tiempo pasa sola cada vaca
alone_time = [0 for _ in range(n)]
# vacas que están trabajando ahora en [prev_time, curr_time]
active = set()
# tiempo del evento anterior
prev_time = 0
# cuánto tiempo cubren todas las vacas juntas
total_time = 0
for e in events:
curr_time = e.time
print(active)
# 1. actualizamos el tiempo total cubierto por todas las vacas
if active:
total_time += curr_time - prev_time
# 2. comprobamos si hay solo una vaca en [prev_time, curr_time]
if len(active) == 1:
alone_time[next(iter(active))] += curr_time - prev_time
# 3. procesamos el evento
if e.is_start:
active.add(e.cow_id)
else:
active.remove(e.cow_id)
# 4. actualizamos prev_time
prev_time = curr_time
print(total_time - min(alone_time), file=open("lifeguards.out", "w"))