//線段樹的實現
#includeusing namespace std;
#define ll long long
#define db double
#define max 10000
#define rep(i,j,k) for(int i=(int)(j);i<=(int)(k);i++)
#define per(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
void down(int k);
struct node
tree[4*max+1]; //樹必須要開4倍空間
//線段樹基礎操作:
/*1.建樹
2.單點查詢
3.單點修改
4.區間查詢
5.區間修改
*///1. 建樹
void build(int l, int r, int k)
int m = (l + r) / 2;
build(l, m, k * 2);//左孩子
build(m, r, k * 2 + 1);//右孩子
tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w; //區間和 把孩子的區間和加起來就是父節點的區間和
}//2.單點查詢
/*ans是查詢的標誌
x是查詢的值
*/void ask(int k,int ans,int x)
if (tree[k].f) down(k); //懶標記下傳
int mid = (tree[k].l + tree[k].r) / 2;
if (x <= mid)
else }
//3.單點修改
/*在修改後 父節點即以上節點的值都需要更新
y是要+上的值
x是需要修改的值 修改後為x+y
*/void add(int k,int x,int y)
if (tree[k].f) down(k); //懶標記下傳
int mid = (tree[k].l + tree[k].r) / 2;
if (x <= mid)
else
//更新
tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w; //節點更新
}//4.區間查詢
/*思路是:
查詢區間為 [x,y]
mid=(l+r)/2
y<=mid 查詢區間全部在當前區間的左子區間,所以左子女區間走
x>mid 查詢區間全部在當前區間的右子區間,所以右子女區間走
否則 兩個區間走
ans 是查詢之和
*/void sum(int k,int x, int y,int ans)
if (tree[k].f) down(k); //懶標記下傳
int mid = (tree[k].l + tree[k].r) / 2;
if (x <= mid)
if (y > mid) }
//5.區間修改
/*修改一段連續區間的值 給區間[a,b]都加上x
在區間修改的過程中,如果我們從最上層開始修改到最底層 那麼複雜度比線性還高 那麼用線段樹根本就沒有什麼意義
還有就是在查詢的時候 如果我們只查詢上層的區間 那麼我們該層以下的所有區間修改都是白費了,那麼如果層數很多 時間複雜度就上去了
所有我們引入乙個標記
引入懶標記
作用:儲存到這個節點的修改資訊,暫時不把修改資訊傳到子節點。
步驟:a.在結構體中新增新的變數 儲存這個懶標記
b.遞迴到這個節點的時候,只更新這個節點的狀態,並把當前的更改值累計到標記中去。
c.當需要遞迴這個節點的子節點的時候,標記再往下傳遞,這樣我們就減少了不必要的下傳操作,可以理解為你想要多少 下傳多少 當你訪問的時候再下傳
d.下傳操作:
① 當前節點的懶標記 累計 到子節點的懶標記中去
② 修改子節點的狀態。 就是 原狀態+子節點區間點的個數*父節點傳下來的懶標記 相當於就是自己的加上每次父節點上傳下來的
③ 父節點懶標記清0 相當於該標記已經傳到了子節點去了 為了避免重複下傳 所以把父節點清0
*///懶標記下傳**
void down(int k)
//區間修改
void add2(int k, int a, int b, int x)
if (tree[k].f)
int mid = (tree[k].r + tree[k].l) / 2;
if (a <= mid) add2(k * 2, a, b, x);
if (b > mid) add2(k * 2 + 1, a, b, x);
//更改區間狀態
tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}int main()
線段樹的實現(模板)
線段樹 在一類問題中,我們需要經常處理可以對映在乙個座標軸上的一些固定線段,例如說對映在ox軸上的線段。由於線段是可以互相覆蓋的,有時需要動態地取線段的並,例如取得並區間的總長度,或者並區間的個數等等。乙個線段是對應於乙個區間的,因此線段樹也可以叫做區間樹。線段樹的構造思想 線段樹是一棵二叉樹,樹中...
線段樹的基本實現
線段樹是這樣一種結構,每個節點儲存陣列一部分的和 原陣列為13 57911 對應的線段樹結構如下 根節點是陣列之和,根節點的左孩子是陣列左半部分之和,根節點的右孩子是陣列右半部分數值之和。中間點 int mid start end 2 int left node 2 node 1 左子樹樹根 int...
RMQ(線段樹實現)
t t第乙個線段樹程式,還沒a過題,不過也很感動,先貼出來 下標從0開始,輸入 1 1 結束.求每一段區間之間的最大值。include include typedef struct treenodenode int mymax int a,int b node buildtree int a,int...