線段樹詳解(洛谷模板題)

2021-08-10 16:06:33 字數 2453 閱讀 1103

線段樹是一種二叉搜尋樹,它將乙個區間分成多個單元區間,每個單元區間對應線段樹的乙個葉子節點,有查詢區間和,查詢區間最大值、最小值等功能(本篇講解的是求區間和的**),由於它二叉結構的特性,使得他的操作複雜讀為o(logn)

線段樹的根節點代表所要維護的值在總區間 [a,b] 的值,他的左子節點代表區間 [a,(a+b)/2] ,他的右子節點代表區間 [(a+b)/2+1,b],對他的左右子節點也同樣如此劃分。

線段樹的操作大致分為建樹、區間修改,下放延遲標記,區間查詢等操作。

void build(int root,int istart,int iend)

int mid=(istart+iend)/2;

build(root*2,istart,mid);//建左子樹

build(root*2+1,mid+1,iend);//建右子數

mem[root].sum=mem[2*root].sum+mem[2*root+1].sum;//區間預處理求和,父節點的值是兩個子節點值的和

}

void update(int root,int istart,int iend,int l,int r,int value)

pushdown(root,iend-istart+1); //下方延遲標記(線段樹的精髓)

int mid=(istart+iend)/2;

update(root*2,istart,mid,l,r,value); //修改左子節點

update(root*2+1,mid+1,iend,l,r,value); //修改右子節點

mem[root].sum=mem[root*2].sum+mem[root*2+1].sum; //區間再次求和,父節點的值是兩個子節點的值的和

}

如果我們在修改區間時,一次全部修改,線段樹的複雜度將大大增加,但如果我們加入了延遲標記,在我們需要使用該區間時進行下放延遲標記,可以將線段樹大大優化

void pushdown(int root,int len)

}

long long query(int root,int istart,int iend,int l,int r)

pushdown(root,iend-istart+1);//下放我們當前正確查詢區間的延遲標記

int mid=(istart+iend)/2;

return query(root*2,istart,mid,l,r)+query(root*2+1,mid+1,iend,l,r);//父節點的值等於左右子節點的值和,我們在此遞迴求解

}

#include#include#include#include#define maxn 1e6+10

using namespace std;

int n,m,k;

int a[1000010];

struct nodemem[1000010];

void build(int root,int istart,int iend)

int mid=(istart+iend)/2;

build(root*2,istart,mid);

build(root*2+1,mid+1,iend);

mem[root].sum=mem[2*root].sum+mem[2*root+1].sum;

}void pushdown(int root,int len)

}void update(int root,int istart,int iend,int l,int r,int value)

pushdown(root,iend-istart+1);

int mid=(istart+iend)/2;

update(root*2,istart,mid,l,r,value);

update(root*2+1,mid+1,iend,l,r,value);

mem[root].sum=mem[root*2].sum+mem[root*2+1].sum;

}long long query(int root,int istart,int iend,int l,int r)

pushdown(root,iend-istart+1);

int mid=(istart+iend)/2;

return query(root*2,istart,mid,l,r)+query(root*2+1,mid+1,iend,l,r);

}int main()

build(1,1,n);

for(int i=1;i<=m;i++)

else

} return 0;

}

線段樹一般在noip中不作為正解出現,不過是暴力的不二之選,只要搞懂了線段樹四種操作,線段樹就可以基本理解了。

線段樹入門詳解,洛谷P3372 模板 線段樹 1

關於線段樹 本隨筆參考例題 p3372 模板 線段樹 1 所謂線段樹就是把一串陣列拆分成乙個乙個線段形成的一棵樹。比如說像這樣的乙個陣列1,2,3,4,5 1 5 1 3 4 5 1 2 345 1 2 如圖所示,這就類似於線段樹。線段樹之所以稱之為樹是因為他分解出來的樣子類似於樹,如上圖所示。1....

洛谷 3372 模板 線段樹 1

題目描述 如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 輸入輸出格式 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數...

線段樹模板 洛谷P2023

傳送門 這個題目的區間更新有加法和乘法。所以比裸的線段樹難一點點吧,也就僅僅是一點點。既然存在兩個操作,所以我們就要維護兩個tag,乙個加法乙個乘法。但是pushdown的時候這兩個tag怎麼pushdown呢?乘法的優先順序顯然比加法高,所以我們在mul更新的時候要先pushdown,這是乙個要點...