Rozważ następujące pytanie Google Code Jam w rundzie 1C :
Wielki Mur Chiński zaczyna się od nieskończonej linii, której wysokość we wszystkich lokalizacjach wynosi .
Pewną liczbę pokoleń , N ≤ 1000 , atakują murze ściany według następujących parametrów - początkowego dnia, D , wytrzymałość początkową S , rozpoczęcie zachód współrzędnych, W i początek wschód współrzędnych, E . Ten pierwszy atak występuje na dzień D , w zakresie [ W , e ] , przy wytrzymałości S . Jeśli w [ W , E ] jest jakaś część Wielkiego Muru , która ma wysokość < S, atak się powiódł, a pod koniec dnia ściana zostanie zbudowana w taki sposób, że każdy jej fragment w obrębie wysokości < S byłby wówczas na wysokości S (lub większej, jeśli jakiś inny atak ten dzień uderzył w ten sam segment siłą S ′ > S )
Każde plemię wykona do ataków przed wycofaniem się, a każdy atak zostanie określony iteracyjnie od poprzedniego. Każde plemię ma trochę δ D , δ X i δ S, które określają ich kolejność ataków: Będzie czekać δ D ≥ 1 dni między atakami, będą przesuwać swój zasięg ataku jednostek za każdy atak (ujemny = zachodni, dodatni = wschód), chociaż rozmiar zasięgu pozostanie taki sam, a ich siła również wzrośnie / zmniejszy się o stałą wartość po każdym ataku.
Celem problemu jest, przy pełnym opisie atakujących plemion, określenie, ile ich ataków odniesie sukces.
Udało mi się napisać kod działającego rozwiązania, które działa w około 20 sekund: Wydaje mi się, że rozwiązanie, które wdrożyłem, zajmuje czas , gdzie A = całkowita liczba ataków w symulacji (maks. 1000000 ), a X = całkowita liczba unikalnych punktów krawędzi w zakresach ataku (maks. 2000000 ).
Na wysokim poziomie moje rozwiązanie:
- Wczytuje wszystkie informacje Plemienia
- Oblicza wszystkie unikalne współrzędne dla zakresów ataku - O ( A )
- Reprezentuje ścianę jako leniwie zaktualizowane drzewo binarne w zakresach które śledzi minimalne wartości wysokości. Liść to rozpiętość dwóch współrzędnych X bez żadnych pośrednich wartości, a wszystkie węzły nadrzędne reprezentują ciągły przedział objęty przez ich dzieci. - O ( X log X )
- Generuje wszystkie ataki, które wykona każde plemię, i sortuje je według dnia -
- Dla każdego ataku sprawdź, czy się powiedzie ( czas kwerendy w ). Gdy dzień się zmieni, przejrzyj wszystkie nieprzetworzone udane ataki i odpowiednio zaktualizuj ścianę ( rejestruj czas aktualizacji X dla każdego ataku). - O ( A log X
Moje pytanie jest następujące: Czy istnieje sposób to zrobić lepiej niż ? Być może jest jakiś strategiczny sposób na wykorzystanie liniowej natury kolejnych ataków Plemion? 20 sekund wydaje się zbyt długie na zamierzone rozwiązanie (choć Java może być za to winna).