當您查詢分段樹中的節點時,需要確保其所有祖先和節點本身都已正確更新。您在訪問查詢節點時執行此操作。
在訪問查詢節點時,您會遍歷從根節點到查詢節點的路徑,同時處理所有掛起的更新。由於您需要訪問O(log N)個祖先,因此對於任何給定的查詢節點,您只需執行O(log N)工作。
這是我的代碼,用於具有惰性傳播的分段樹。
// interval updates, interval queries (lazy propagation)
const int SN = 256; // must be a power of 2
struct SegmentTree {
// T[x] is the (properly updated) sum of indices represented by node x
// U[x] is pending increment for _each_ node in the subtree rooted at x
int T[2*SN], U[2*SN];
SegmentTree() { clear(T,0), clear(U,0); }
// increment every index in [ia,ib) by incr
// the current node is x which represents the interval [a,b)
void update(int incr, int ia, int ib, int x = 1, int a = 0, int b = SN) { // [a,b)
ia = max(ia,a), ib = min(ib,b); // intersect [ia,ib) with [a,b)
if(ia >= ib) return; // [ia,ib) is empty
if(ia == a && ib == b) { // We push the increment to 'pending increments'
U[x] += incr; // And stop recursing
return;
}
T[x] += incr * (ib - ia); // Update the current node
update(incr,ia,ib,2*x,a,(a+b)/2); // And push the increment to its children
update(incr,ia,ib,2*x+1,(a+b)/2, b);
}
int query(int ia, int ib, int x = 1, int a = 0, int b = SN) {
ia = max(ia,a), ib = min(ib,b); // intersect [ia,ib) with [a,b)
if(ia >= ib) return 0; // [ia,ib) is empty
if(ia == a && ib == b)
return U[x]*(b - a) + T[x];
T[x] += (b - a) * U[x]; // Carry out the pending increments
U[2*x] += U[x], U[2*x+1] += U[x]; // Push to the childrens' 'pending increments'
U[x] = 0;
return query(ia,ib,2*x,a,(a+b)/2) + query(ia,ib,2*x+1,(a+b)/2,b);
}
};
當我實現了一個段樹,我必須做同樣的事情。您設置[0-> 4]節點,標記每個子節點,然後將父節點更新到根節點。 – Justin
所以你的更新是O(logN)?另外,在細分樹中,如果我的範圍是2到7,我會更新3個細分。 RT? [2 2],[3 4] [5 7] – Pranalee
O(2 * logn)更新。是的,這是最糟糕的一種更新。如果有人知道更好的方法,我會很好奇。 – Justin