Sto cercando di risolvere il problema rangetree1.
Io non l’ho risolto così. Cioè portavo con me due flag: outdated, inverti. I nodi outdated erano tutti quelli coinvolti dalla radice fino al nodo da invertire (incluso). Quando facevo la query andavo a vedete se un nodo era outdated ed in caso affermativo andavo a cercare tutti i nodi figli che lo erano (controllando se era da invertire ed in caso propagando l’evento) e quando arrivavo ad un nodo che aveva figli !outdated sommavo i loro valori per metterli in quelli del padre e così ricorsivsmente fino a quando non settavo il nodo a !outdated (sommando i suoi figli che ormai non lo erano più). Non so se ho reso l’idea
non ho capito la differenza fra il flag outdated e inverti…
Mmm infatti non mi sono spiegato bene. Un nodo che ha il flag inverti ha anche il flag outdated, però non vale il contrario. Questo perché se ad esempio ho un flag inverti al nodo che gestisce il range [3,4] e faccio una query sul range [1,4], questo non sarà aggiornato però andrò a vedere lo stesso i suoi figli (e quindi trovare quello da invertire) grazie al flag outdated.
Io l’ho risolto in un altro metodo. Per ogni nodo mi tengo il numero di teste e il numero di capovolgimenti. Quando faccio un update, se il range del nodo è completamente contenuto nel range del’update aumento il capovolgi di uno e ritorno, altrimenti richiamo i due figli e aggiorno il valore delle teste (Facendo una query per ciascun nodo) e ritorno. Per la ricerca,invece, se il range del nodo è completamente dentro ritorno il numero di teste(se capov%2==0) o fine-inizio-teste+1. Se il range non è completamente contenuto, ritorno la somma della ricerca sui due figli.
ma… il flag inverti significa che tutto il range gestito dal nodo va invertito giusto? il flag outdated invece?
Per dire se un nodo è aggiornato o meno. Infatti se c’è un nodo discendente da invertire, questo nodo non sarà aggiornato e io me lo segno col flag outdated.
Per dire se un nodo è aggiornato o meno. Infatti se c'è un nodo discendente da invertire, questo nodo non sarà aggiornato e io me lo segno col flag outdated.Lawliet
Sì è giusto
questo codice fa giusto il primo test case, poi metà li sbaglia e per metà va fuori tempo…
I controlli falli in questo modo:
if(a >= tree[index].s && b <=tree[index].e)
quali controlli? ce ne sono tanti…
Forse fai prima a postare direttamente il tuo codice perché l’algoritmo l’ho capito ma c’è qualcosa che non va nella mia implementazione…
Sbagli sia nell’implementazione del St, che nel change, che nella query.
create(tree, 1, 0, n-1); //la dimensione non ti serve
Ed inoltre dovresti anche correggere la procedura in questo modo:
tree[index].value = 0; tree[index].inverti = 0; tree[index].aggiornato = 1; tree[index].s = s; tree[index].e = e; create(tree, n, index2, s, (s+e)/2); create(tree, n, index2+1, (s+e)/2+1, e);
if(tree[index].s>b || tree[index].e<a)
return;
Poi non devi dire di capovolgere il range solo se stai esattamente nel range, ma è sufficiente che il nodo che stai considerando ne copra una parte. Cioè se devi capovolgere tutte le monete da [1,3] (in un range totale che va da 1 a 4), devi capovolgere i segmenti [1,2] e [3,3], in quanto il segmento [1,3] nell’albero non esiste.
Quindi:
if(tree[index].s>=a && tree[index].e<=b){
tree[index].inverti = (tree[index].inverti+1)%2;
tree[index].aggiornato = 0;
return; //non hai altro da fare in questo nodo
}
Se non sei nè fuori, nè dentro al range, visiti entrambi i figli. Inoltre sbagli anche a fare le visite. Infatti unisci le due implementazioni di un segment Tree, cioè quella che prevede il passaggio per parametri di L ed R (left e right) del segmento che visiti e quella che invece li memorizza nel nodo stesso. Quindi dopo queste due condizioni continui così:
tree[index].aggiornato=0;
change(tree, n, index2, a, b);
change(tree, n, index2+1, a, b);
//devi lasciare a e b che è il range iniziale da considerare
E così hai terminato il change:
void change(struct nodo tree[], int index, int a, int b){ //n non serveif(tree[index].s>b || tree[index].e<a)
return;
if(tree[index].s>=a && tree[index].e<=b){
tree[index].inverti = (tree[index].inverti+1)%2;
tree[index].aggiornato = 0;
return; //non hai altro da fare in questo nodo
}tree[index].aggiornato=0;
}
change(tree, n, index*2, a, b);
change(tree, n, index*2+1, a, b);
Prova a correggere la query da solo, tanto gli errori sono più o meno gli stessi.
Sembrerebbe corretto… Lento ma corretto. Il problema è che ti va in timeout o ci sono output non corretti anche?
il secondo task è sbagliato, poi ci sono un po’ di Execution killed with signal 11 e un po’ di timeout
Il vettore tree dev’essere dimensionato a 4n. Comunque se ancora non va, posta il codice completo per favore.