Ngoaho91'in cevabını tamamlamak için.
Bu sorunu çözmenin en iyi yolu, Segment Ağacı veri yapısını kullanmaktır. Bu, O (log (n)) içindeki bu tür sorguları yanıtlamanıza izin verir, bu da algoritmanızın toplam karmaşıklığının O (Q logn) olacağı anlamına gelir; burada Q, sorgu sayısıdır. Saf algoritmayı kullandıysanız, toplam karmaşıklık O (Qn ) olacaktır ki bu daha yavaştır.
Bununla birlikte, Segment Ağaçlarının kullanımının bir dezavantajı vardır. Çok fazla bellek gerektirir, ancak çoğu zaman bellekle ilgili hızdan daha az önem verirsiniz.
Bu DS tarafından kullanılan algoritmaları kısaca anlatacağım:
Segment ağacı, her düğümün atandığı aralığın değerini tuttuğu İkili Arama Ağacının özel bir örneğidir. Kök düğüme [0, n] aralığı atanır. Sol çocuğa [0, (0 + n) / 2] ve sağ çocuğa [(0 + n) / 2 + 1, n] atanır. Bu şekilde ağaç inşa edilecek.
Ağaç Yarat :
/*
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.
}
}
Sorgu Ağacı
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.
}
Daha fazla açıklamaya ihtiyacınız varsa, bana bildirin.
BTW, Segment Ağacı, O öğesindeki tek bir öğenin veya bir dizi öğenin güncellenmesini de destekler (log n)