Metoda događaja (sweep line)

Lekcija 4 od 7 · Napredne tehnike

Zamislimo vertikalnu liniju koja prelazi preko brojevne prave sleva nadesno i zaustavlja se samo na zanimljivim mestima – događajima: početku i kraju intervala. Umesto da proveravamo svaku tačku, sortiramo događaje i obrađujemo ih redom. Tako se rešavaju zadaci sa intervalima, rasporedima i preklapanjima.

Pre nego što počneš: potrebno predznanje – funkcija sort, prefiksne sume.
Kako da učiš: svaki primer prekucaj i pokreni, a zadatke na kraju prvo reši sam/a; uputstvo i rešenje otvori tek posle toga. Svi programi su u C++-u.

Najviše istovremenih intervala

U muzeju je bilo n posetilaca; za svakog znamo vreme dolaska a i odlaska b. Koliko je najviše ljudi bilo istovremeno? Svaki posetilac daje dva događaja: (a, +1) i (b, −1). Sortiramo događaje po vremenu i prolazimo, menjajući brojač.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<pair<int, int>> dog;                // (vreme, promena)
    for (int i = 0; i < n; i++) {
        int a, b;
        cin >> a >> b;
        dog.push_back({a, +1});                // dolazak
        dog.push_back({b, -1});                // odlazak
    }
    sort(dog.begin(), dog.end());              // kod istog vremena -1 ide pre +1
    int trenutno = 0, naj = 0;
    for (auto &d : dog) {
        trenutno += d.second;
        naj = max(naj, trenutno);
    }
    cout << naj << endl;
    return 0;
}

Parovi se sortiraju po vremenu, a kod jednakog vremena po drugoj vrednosti: −1 pre +1. To znači da posetilac koji odlazi u trenutku 4 i onaj koji dolazi u trenutku 4 nisu istovremeno u muzeju. Ako se po postavci računaju kao istovremeni, odlazak se kodira sa vremenom b + 1 ili se menja redosled.

Ukupna pokrivena dužina

Na pravoj je nacrtano n duži [a, b]. Kolika je ukupna dužina koju pokriva bar jedna duž? Pri prolasku pamtimo koliko duži trenutno pokriva liniju; deo između dva uzastopna događaja ubrajamo ako je brojač veći od 0.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<pair<long long, int>> dog;
    for (int i = 0; i < n; i++) {
        long long a, b;
        cin >> a >> b;
        dog.push_back({a, +1});
        dog.push_back({b, -1});
    }
    sort(dog.begin(), dog.end());
    long long ukupno = 0;
    int aktivnih = 0;
    for (size_t i = 0; i < dog.size(); i++) {
        if (i > 0 && aktivnih > 0) ukupno += dog[i].first - dog[i - 1].first;   // deo od prethodnog događaja
        aktivnih += dog[i].second;
    }
    cout << ukupno << endl;
    return 0;
}

Duži [1, 4] i [2, 6] zajedno pokrivaju [1, 6] (dužina 5), a [8, 10] još 2 – ukupno 7. Isti rezultat daje i spajanje intervala.

Veza sa nizom razlika

Kada su vremena mali celi brojevi (do 106), umesto sortiranja događaja može se koristiti niz razlika: d[a]++, d[b]--, pa prefiksna suma daje broj aktivnih intervala u svakoj tački. Metoda događaja radi i kada su vremena velika (do 109) ili realna – zato je opštija.

Zadaci za vežbu

Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.

ZADATAK 01Težina: Srednje

Broj potrebnih sala

Za n predavanja data su vremena početka i kraja [s, e) (predavanje koje se završava u 10 i ono koje počinje u 10 mogu biti u istoj sali). Koliko je najmanje sala potrebno?

Primer 1

Ulaz

3
0 30
5 10
15 20

Izlaz

2

Primer 2

Ulaz

2
1 10
10 20

Izlaz

1
ZADATAK 02Težina: Srednje

Najduži period bez posetilaca

Muzej radi od trenutka 0 do T. Dati su intervali boravka n posetilaca. Koliko traje najduži neprekidan period u kome u muzeju nije bilo nikoga?

Primer 1

Ulaz

10 2
2 4
3 6

Izlaz

4

Primer 2

Ulaz

5 1
0 5

Izlaz

0
Česte greške i saveti
  • Pažljivo odluči redosled događaja u istom trenutku (kraj pre početka ili obrnuto) – zavisi od postavke.
  • Događaje čuvaj kao parove i sortiraj ih; ne prolazi kroz sva moguća vremena ako su do 109.
  • Brojač aktivnih intervala nikad ne sme biti negativan – ako jeste, redosled događaja je pogrešan.

Proveri znanje

Otvori kviz

Metoda događaja

1. Koliko događaja daje jedan interval [a, b]?




2. Koja je složenost metode događaja za n intervala?




3. Najmanji broj sala za predavanja jednak je…