Mark hai qualche idea per risolvere vasi2?
vediamo se ho capito:Sostanzialmente non dovresti usare remove e search ma le funzioni per aggiungere e togliere valori dalla fine è dll'inizio della lista (push_back(), push_front(), pop_back(), pop_front()) per tutte le liste "centrali" tra i due indici coinvolti nell'update. Per i segmenti che invece contengono questi due indici devi usare remove e insert. Il problema è che le liste sono lente, quindi ti conviene usare varie deque.Esatto, dato che pop/push_back e pop/push_front hanno coplessità costante (O(1)). Quindi ti fai un vettore di sqrt(N) deque, ognuna con sqrt(N) elementi (o meno, nel caso dell'ultima, dato che sqrt(N) non è sempre un intero).La complessità migliora perché tu fai solo 2 operazioni per ogni segmento, diventando quindi O(2*sqrt(N))=O(sqrt(N)).Non so se sono stato chiaroLawliet
mark03
Esempio:
deck[0] = {0, 1, 2}
deck[1] = {3, 4}
Per eseguire
s 2 4
faccio:
deck[1].push_back(deck[0].back());
deck[0].pop_back();
deck[0].push_back(deck[1].front());
deck[1].pop_front();
E nel caso fosse
s 1 3
come farei?
dovrei levare il 2 poi l'1, poi rimettere il 2, levare il 4 inserire l' 1 e rimettere il 4
deck[0] = {0, 1, 2}
deck[1] = {3, 4}
int temp=deck[0][2]; //salvo il valore;
deck[0].erase(deck[0].begin()+2); // lo tolgo
deck[0].push_back(deck[1].front()); //sposto il valore
deck[1].pop_front(); // lo rimuovo
deck[1].insert(deck[1].begin()+1,temp); // lo reinserisco
Io sìP.S: ci sarete tutti e due alle OII a settembre?mark03
yes (y)Io sìP.S: ci sarete tutti e due alle OII a settembre?mark03
Lawliet
Qualche guru che possa illuminarmi nella risoluzione di vasi2?
Allora perchè la ricerca dovrebbe avere complessità O(N/M) + O(M) ??Io intendevo "è facile trovare un modo di farlo in in O(N/M) + O(M)", il vostro metodo (che usa la divisione per M e il modulo per M) chiaramente impiega O(1). Però assume che gli array (a parte l'ultimo) siano tutti lunghi esattamente M. Il problema però è quando si va a fare l'update questa assunzione potrebbe smettere di essere vera.simone.pri
L'assunzione non smette di essere vera, però, se si spostano anche tutti gli intervalli intermedi (mettendo il primo del successivo alla fine del precedente, o viceversa nel caso in cui lo spostamento sia al "contrario", ovvero da una posizione più grande a una più piccola).Allora perchè la ricerca dovrebbe avere complessità O(N/M) + O(M) ??Io intendevo "è facile trovare un modo di farlo in in O(N/M) + O(M)", il vostro metodo (che usa la divisione per M e il modulo per M) chiaramente impiega O(1). Però assume che gli array (a parte l'ultimo) siano tutti lunghi esattamente M. Il problema però è quando si va a fare l'update questa assunzione potrebbe smettere di essere vera.simone.pri
wil93
Sì, “potrebbe” cioè dipende da come si decide di implementare l’update. Col vostro metodo il “find” è più veloce dell’update, c’è un’altra soluzione in cui è l’opposto… ma vabbé, funzionano entrambe
Sì, "potrebbe" cioè dipende da come si decide di implementare l'update. Col vostro metodo il "find" è più veloce dell'update, c'è un'altra soluzione in cui è l'opposto... ma vabbé, funzionano entrambe :)Io l'ho risolto (vasi1) con update in O(sqrt(N)) e find in O(1). Ma ci sono soluzioni molto più veloci (o meglio ottimizzate ahaha)UPD: Anzi no, probabilmente nell'altro metodo sono uguali... quindi direi che il vostro è migliore :)wil93
Nemmeno io riesco a risolverlo…
Come suggerito in questo topic, ho creato un array lungo √N di deque, ciascuna con √N elementi. La ricerca è semplicemente
return blocks[i / sqrtN][i % sqrtN]
dove blocks è l’array di deque. L’update invece è
if(i == j) return;
int v_i = query(i);
int b = i / sqrtN;
blocks[b].erase(blocks[b].begin() + (i % sqrtN));
if(i < j) {
while(b < j / sqrtN) {
blocks[b].push_back(blocks[b + 1].front());
blocks[++b].pop_front();
}
blocks[b].insert(blocks[b].begin() + (j % sqrtN), v_i);
}
e analogamente se i > j.
Mi sembra tutto corretto, eppure va in Time Limit in un paio di testcase. Cosa sto sbagliando?
L’algoritmo è corretto. Magari prova a mettere il risultato di j/sqrtN in una variabile. Poi prova a rimandare semplicemente la soluzione. Spesso fa così se il server in quel momento era occupato.
Niente da fare, va ancora in Time Limit Exceeded. Proverò a risottometterlo occasionalmente. Grazie comunque per l’aiuto!
Ma mi sembra strano che non te lo faccia perché comunque l’algoritmo è quello
A quanto pare per risolvere vasi2 servono un’update e una ricerca in tempo logaritmico.
A quanto pare per risolvere vasi2 servono un'update e una ricerca in tempo logaritmico.Questo mi fa subito pensare ai segment oi fenwick, per dubito sia cosi banale..EmanueleRossi
Forse segment tree?
Appena ho il tempo butto giù un algoritmo perché forse ho in mente qualcosa con un segment tree con complessità di update e di ricerca entrambe O(logN)
Noi comunque aspettiamo l’illuminazione di qualche guru
Ho anch’io un problemino con vasi. Mi sembra che il mio algoritmo coincida con quello che dite qui ma va in timeout in 3 casi dell’ultima subtask di circa mezzo secondo.Secondo voi,perchè?