線段樹定義理解與模板

2021-09-25 23:11:16 字數 3460 閱讀 6489

超級開心,今天的屁屁踢有詳細注釋!(雖然這仍然彌補不了我抄錯模板的事實。。。)

今天七夕,雖然我不過節,但是讓我應景的來一句土味情話(對每乙個我a出來的題):我能想到最浪漫的事,就是看著你由wa到t,再t又t還t,ttttttt,最終成為那抹綠色靚麗的ac(撒花~~~)

廢話不再說,附上具有詳細注釋的帶有我個人理解的模板**!

void build(int rt,int l,int r)//rt為當前建立的節點編號(下標),l、r為rt維護的區間的左右端點

int m = (l+r)>>1;//m為該節點左孩子區間的右端點

build(rt<<1,l,m);//rt<<1為該節點左孩子下標

build(rt<<1|1,m+1,r); //rt<<1|1 == rt*2+1 為該節點右孩子編號

push_up(rt);//該函式作用是將子樹資訊向上更新,更新到父節點上

} void push_up(int rt)

//以更新和為例

build(1,1,n);//函式呼叫

void update(int rt,int l,int r,int p,int v)//rt為正在遍歷的節點下標,l,r為rt的區間左右端點,p為需要更改的節點下標,v為修改值(此處以v為增加的值為例)

int m=(l+r)>>1;//m為rt節點的左右孩子的區間分界線

if(p <= m)//當需要更新的p節點在左孩子所維護區間

else//當需要更新的p節點在右孩子所維護區間

push_up(rt);//將子樹資訊更新到父節點

} update(1,l,n,p,v)//函式呼叫

int query(int rt,int l,int r,int ll,int rr)// rt為正在遍歷到的節點下標,l,r為rt的區間端點,ll,rr為查詢的區間端點 

int res=0;//返回值變數,初始化視情況而定

int m=(l+r)>>1;//m為rt左右孩子分界線

if(ll<=m)//如果查詢區間與左孩子有交集

if(rr>m)//如果查詢區間與右孩子有交集

return res;

} query(1,l,r,ll,rr)//函式呼叫

我們引入了變數—懶標記(lazy),顧名思義懶標記懶標記,就是我們懶得修改從而打的標記,我們如何懶且能使答案正確呢,我們知道我們只需要修改區間(l,r),我們需要修改的點維護的區間一定在需要修改的區間內,因此如果乙個節點再需要修改的區間內,我們可以直接修改乙個大區間相對應的值,並不需要修改它的子節點,等我們需要單獨提出該子節點的資訊的時候在下傳這個懶標記並修改這個子節點,這樣我們可以在o(log n)的情況下完成一整個區間的修改了,對於查詢區間相似的我們只需要查詢完全在修改區間內的數值即可.

void update(int rt,int l,int r,int ll,int rr,int v)//rt為正在遍歷到的節點下標,l,r為rt的區間端點,ll,rr為查詢的區間端點 ,v為區間修改的值(以區間每個數都加v為例) 

push_down(rt,l,r);//查詢lazy標記,更新子樹

int m=(l+r) >> 1;//m為子樹的左右分界線

if(ll<=m) update(rt<<1,l,m,ll,rr,v);//如果左子樹和需要更新的區間交集非空 ,更新左子集

if(rr>m) update(rt<<1|1,m+1,r,ll,rr,v);//如果右子樹和需要更新的區間交集非空 ,更新右子集

push_up(rt);//更新父節點

} void push_down(int rt,int l,int r)//更新查詢到的子樹的值

} update(1,l,r,ll,rr,val)//函式呼叫

int query(int rt,int l,int r,int ll,int rr)// rt為正在遍歷到的節點下標,l,r為rt的區間端點,ll,rr為查詢的區間端點 

push_down(rt,l,r);//每次訪問都檢查lazy標記

int m=(l+r)>>1;//m為rt左右孩子分界線

long long res=0;//返回值變數,初始化視情況而定

if(ll<=m)//如果查詢區間與左孩子有交集

if(rr>m)//如果查詢區間與右孩子有交集

return res;

} query(1,1,n,ll,rr)//函式呼叫

#include #include using namespace std;

const int maxn=1000010;

int sum[maxn*4];

int lazy[maxn*4];

void build(int rt,int l,int r)//建樹

int m = (l+r)>>1;

build(rt<<1,l,m);

build(rt<<1|1,m+1,r);

push_up(rt);

}void push_up(int rt)

void update(int rt,int l,int r,int p,int v)//點修改

int m = (l+r) >> 1;

if(p <= m)

else

push_up(rt);

}void update(int rt,int l,int r,int ll,int rr,int v)//區間修改

push_down(rt,l,r);

int m = (l+r)>>1;

if(ll<=m)

if(rr>m)

push_up(rt);

} void push_down(int rt,int l,int r) }

int query(int rt,int l,int r,int ll,int rr)//區間查詢

push_down(rt,l,r);

int m = (l+r)>>1;

long long res=0;

if(ll<=m) res+=query(rt<<1,l,m,ll,rr);

if(rr>m) res+=query(rt<<1|1,m+1,r,ll,rr);

return res;

}int main()

最後來張萌圖,(*^__^*) 嘻嘻……

C typedef 結構體指標定義理解

在c語言裡面,struct是用來定義新的資料型別 結構體,typedef是給資料型別取別名。typedef struct filefileinfo typedef struct filefileinfo,filep 例如 typedef struct lnode lnode,linklist 相當於...

線段樹模板(模板)

參考部落格 持續更新。外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳 img xhrgdjcd 1613976863463 區間儲存在陣列中的下標對應為 12 3 4 5 6 7 8 9 10 11 12 13 14 15 四部分單點更新 根據題目的要求編寫自己的pushup,query...

線段樹模板

include include include using namespace std const int size 10010 struct node the node of line tree class linetree void updatem void updateline public ...