Cerință
Ai o listă de melodii pe Spotify (deși probabil ar trebui să folosești YouTube Music... ). De vreme ce foamea este mare, cei de la Spotify au decis să adauge reclame înainte și după fiecare melodie. Mai precis, vei avea secunde de reclame după melodia , respectiv secunde de reclame înainte de melodia .
Ai descoperit că, dacă asculți piesele în playlist-uri, aplicația Spotify are bug-uri și ajungi să primești mai puține reclame (bineînțeles că e un bug, doar nu te gandeai că ar face asta pentru ca sunt ei prea drăguți, nu???). Mai exact, dacă formezi un playlist din melodiile , vei primi secunde de reclame.
Acum, tu vrei să împarți cele melodi în playlist-uri astfel încât numărul total de secunde în care asculți reclame să fie cât mai mic. A se nota că poți asculta melodiile în ce ordine vrei.
De vreme ce ești destul de șomer, ai decis să rezolvi această problemă pentru scenarii de forma - dacă consider doar melodiile , care este numărul minim de secunde pe care le voi petrece ascultând reclame?
Această problemă trebuie rezolvată online, prin urmare, scenariile trebuie rezolvate în ordine. Mai exact, veți primi un parametru numit (acesta fiind un seed), iar query-urile se vor genera de concurenți folosind următoarea clasă.
#include <cstdint>
#include <utility>
#include <algorithm>
class QueryGenerator {
public:
QueryGenerator(int N, uint64_t seed)
: N(N), state(seed) {}
inline std::pair<int, int> next_query(int64_t last_answer) {
state ^= (uint64_t)last_answer + 0x9e3779b97f4a7c15ULL + (state << 6) + (state >> 2);
auto l = split_mix_64(state) % N;
auto r = split_mix_64(state) % N;
return {std::min(l, r), std::max(l, r)};
}
private:
uint64_t split_mix_64(uint64_t &x) {
uint64_t z = (x += 0x9e3779b97f4a7c15ULL);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
return z ^ (z >> 31);
}
int N;
uint64_t state;
};
Un exemplu de cum trebuie folosită această clasă:
uint64_t state;
std::cin >> state;
QueryGenerator generator(N, state);
int64_t last_answer = 0;
for (int q = 0; q < Q; q++) {
const auto query = generator.next_query(last_answer);
answer = solve(query.first, query.second);
std::cout << answer << "\n";
last_answer = answer;
}
În caz că doriți să vedeți un exemplu mai detaliat, aveți la atașamentele problemei (în dreapta) încă un exemplu de folosire.
Date de intrare
Pe prima linie se găsesc două numere naturale, și . Pe a doua linie se găsesc numere naturale separate prin spații, reprezentând șirul . Pe a treia linie este descris in mod analog șirul .
Pe ultima linie se găsește numărul , indicât parametrul de stare al clasei de generare a query-urilor.
Date de ieșire
Se vor afișa numere, al -lea dintre ele fiind răspunsul pentru cel de al -lea scenariu, în ordinea în care acestea apar în fișierul de intrare.
Restricții și precizări
- .
- .
- Parametrul se încadrează pe 64 de biți fără semn (uint64_t / unsigned long long).
- Valorile și vor fi în intervalul .
- .
- Pentru teste în valoare de 7 puncte, .
- Pentru teste în valoare de alte 6 puncte, .
- Pentru teste în valoare de alte 14 puncte, .
- Pentru teste în valoare de alte 19 puncte, .
- Pentru teste în valoare de alte puncte, .
- Pentru teste în valoare de alte de puncte, .
Exemplul 1
stdin
3 3
1 4 7
2 6 3
37835487345
stdout
3
7
3
Query-urile care sunt generate sunt , , .
Pentru primul query, vom forma playlist-ul -» .
Pentru al doilea query, vom forma două playlist-uri: și -» .