線段樹區間操作總結

2021-09-12 02:51:11 字數 2287 閱讀 3255

昨天覆習了幾個月前自己寫下的線段樹區間操作總結的演算法筆記,雖然注釋很多,但重新再看時發現注釋仍然不夠。於是這次重新複習了線段樹區間操作演算法,已乙個初學者的角度來加上許多注釋和筆記。我將線段樹的區間操作,包括區間運算,區間求值封裝到了乙個類裡。兩種操作又包含普通版和lazy標籤版,下面是**:

#include#include#includeusing namespace std;

const int maxn=10000;

/*演算法**現的左和右變數有很多不同的含義,需要區分清楚:

一是問題給出的陣列,(待求陣列)

二是保二叉樹的陣列,(儲存陣列) 待求陣列在這個陣列的最後,相當於子葉,前面是父節點

三是對儲存陣列的抽象。(滿二叉樹) 根節點編號為1,對應上面兩個陣列的0

以根節點為例,節點編號使用二叉樹編號0,其覆蓋的範圍用儲存陣列編號,覆蓋全部,所以是0~(子葉數量)

*/class tree

int m=(l+r)/2;

fun1(o*2,l,m);

fun1(o*2+1,m+1,r);

node[o] = node[o*2]+node[o*2+1];}/*

更新節點lazy標籤又add2()呼叫,使用lazy操作的二叉樹符合下面的條件:

1,有lazy標籤的節點的實際值就是實際值,上面全部父節點的當前值也是實際值

2,lazy標籤的節點覆蓋的全部節點的實際值都是當前值加上lazy操作

3,lazy標籤下面的全部子節點都不會出現lazy標籤

4,包含lazy標籤的節點,其左右子樹都是對稱的

*///更新節點操作,又fun2()呼叫,將o節點的lazy標籤轉移到兩個子節點,

void update(int o,int l,int r)

/*區間運算操作2:使用lazy標籤。與區間求和操作1相似,都是從更節點開始向下遞迴操作,但這時若遇到當前節點覆蓋的範圍

完全在需要操作的範圍的情況就可以為其加上lazy標籤,從而代替更新它全部子節點的值的操作。需要注意的是如果當前節點

不符合上面條件需要繼續進入子節點時,需要先消除它的lazy標籤,也就是將lazy標籤向下移一層,然後在遞迴。

*///又add2()呼叫,以lazy思想實驗線段樹區間運算操作

void fun2(int o,int l,int r)else

} /*區間求和操作1:從下往上版。主要操作物件是二叉樹陣列中需要操作的範圍兩邊代表的左子葉和右子葉。需要了解乙個規律,

若左邊界是右子葉或右邊界是左子葉,那麼父親就包含了範圍外的值,需要轉跳節點。另外,結束的條件是左右邊界相鄰。

這是有兩種情況,父親相同或不相同,需要區分對待操作。

*///求葉子s到e的數值和(初級區間求和)

int ask_sum(int s,int e) else e/=2;

if(s%2==1) else s/=2;

}if(s!=e) ans += node[s]+node[e];

else ans+=node[s];

return ans;

}//又ask_sum2()呼叫,對含有lazy標籤的樹進行區間求和操作,順便更新部分節點 ///有誤 (待修改)

void fun3(int o,int l,int r)else

} public:

tree(int n)

~tree()

//為樹葉a進行加減n運算,然後向上更新節點(單點賦值)

void add1(int a,int n)

}//區間賦值操作,為l到r範圍的樹葉加減n運算,更新上面的節點。

void add2(int l,int r,int n)

//區間賦值操作使用lazy減少工作量

void add3(int l,int r,int n)

//當樹使用lazy標籤時使用特殊的區間求值操作,順便更新部分節點

int ask_sum2(int l,int r)

//輸出從葉n到根節點的值

void test(int n)

//前序遍歷 ,先訪問根節點,再左子樹,再右子樹。

void peroder(int n)

//後序遍歷 ,先訪問左子樹,再右子樹,最後根節點。

void lastoder(int n)

};int main() ;

for(int i=0; i<8; i++)

int t,a,b,c;

while(cin>>t)

if(t==3)

}return 0;

}

線段樹區間操作

要求單點修改,區間求和,區間取模 由於乙個數只能被取模log次,所以區間取模就變成了單點修改,同時對區間維護乙個mx值,如果mx小於模數就不取模 include define ll long long using namespace std const int maxn 100000 10 int ...

線段樹的區間操作 板

區間操作 struct node tr maxn 2 節點型別 void pushup int m void build int m,int l,int r 如果只有乙個節點 int mid l r 1 build m 1,l,mid build m 1 1,mid 1,r 建好左右半邊 pushu...

線段樹 (區間和 單點操作)

include include include include include include include include include include define fast ios sync with stdio false define ll long long pragma gcc o...