Zur Ergänzung der Antwort von ngoaho91.
Der beste Weg, um dieses Problem zu lösen, ist die Verwendung der Segmentbaum-Datenstruktur. Auf diese Weise können Sie solche Abfragen in O (log (n)) beantworten. Dies bedeutet, dass die Gesamtkomplexität Ihres Algorithmus O (Q logn) ist, wobei Q die Anzahl der Abfragen ist. Wenn Sie den naiven Algorithmus verwenden würden, wäre die Gesamtkomplexität O (Q n), was offensichtlich langsamer ist.
Es gibt jedoch einen Nachteil bei der Verwendung von Segmentbäumen. Es nimmt viel Speicher in Anspruch, aber oft interessiert Sie weniger das Gedächtnis als die Geschwindigkeit.
Ich werde kurz die von diesem DS verwendeten Algorithmen beschreiben:
Der Segmentbaum ist nur ein Sonderfall eines binären Suchbaums, bei dem jeder Knoten den Wert des Bereichs enthält, dem er zugewiesen ist. Dem Wurzelknoten wird der Bereich [0, n] zugewiesen. Dem linken Kind wird der Bereich [0, (0 + n) / 2] und dem rechten Kind [(0 + n) / 2 + 1, n] zugewiesen. Auf diese Weise wird der Baum gebaut.
Baum erstellen :
/*
A[] -> array of original values
tree[] -> Segment Tree Data Structure.
node -> the node we are actually in: remember left child is 2*node, right child is 2*node+1
a, b -> The limits of the actual array. This is used because we are dealing
with a recursive function.
*/
int tree[SIZE];
void build_tree(vector<int> A, int node, int a, int b) {
if (a == b) { // We get to a simple element
tree[node] = A[a]; // This node stores the only value
}
else {
int leftChild, rightChild, middle;
leftChild = 2*node;
rightChild = 2*node+1; // Or leftChild+1
middle = (a+b) / 2;
build_tree(A, leftChild, a, middle); // Recursively build the tree in the left child
build_tree(A, rightChild, middle+1, b); // Recursively build the tree in the right child
tree[node] = max(tree[leftChild], tree[rightChild]); // The Value of the actual node,
//is the max of both of the children.
}
}
Abfragebaum
int query(int node, int a, int b, int p, int q) {
if (b < p || a > q) // The actual range is outside this range
return -INF; // Return a negative big number. Can you figure out why?
else if (p >= a && b >= q) // Query inside the range
return tree[node];
int l, r, m;
l = 2*node;
r = l+1;
m = (a+b) / 2;
return max(query(l, a, m, p, q), query(r, m+1, b, p, q)); // Return the max of querying both children.
}
Wenn Sie weitere Erklärungen benötigen, lassen Sie es mich einfach wissen.
Übrigens unterstützt der Segmentbaum auch die Aktualisierung eines einzelnen Elements oder einer Reihe von Elementen in O (log n).