線段樹再整理

2022-05-15 21:33:10 字數 3375 閱讀 5453

**和思路來自:傳送門

建樹模板、

//

一:線段樹基本概念

//1:概述

//線段樹,類似區間樹,是乙個完全二叉樹,它在各個節點儲存一條線段(陣列中的一段子陣列),

//主要用於高效解決連續區間的動態查詢問題,由於二叉結構的特性,它基本能保持每個操作的複雜度為o(lgn)!

//性質:父親的區間是[a,b],(c=(a+b)/2)左兒子的區間是[a,c],右兒子的區間是[c+1,b],線段樹需要的空間為陣列大小的四倍

#includeusing

namespace

std;

const

int qq=256

;int segtree[(qq<<2)+10

];int

array[qq];

void build(int node,int l,intr)}

intmain()

//此模板用於查詢區間最小值、

對應查詢函式模板、

//

區間查詢int query(int node, int begin, int end, int left, int right);

//(其中node為當前查詢節點,begin,end為當前節點儲存的區間,left,right為此次query所要查詢的區間)

//主要思想是把所要查詢的區間[a,b]劃分為線段樹上的節點,然後將這些節點代表的區間合併起來得到所需資訊

//比如前面乙個圖中所示的樹,如果詢問區間是[0,2],或者詢問的區間是[3,3],不難直接找到對應的節點回答這一問題。但並不是所有的提問都這麼容易回答,

int query(int node,int begin,int end,int l,intr)

//可見,這樣的過程一定選出了盡量少的區間,它們相連後正好涵蓋了整個[left,right],沒有重複也沒有遺漏。

//同時,考慮到線段樹上每層的節點最多會被選取2個,一共選取的節點數也是o(log n)的,因此查詢的時間複雜度也是o(log n)。

//線段樹並不適合所有區間查詢情況,它的使用條件是「相鄰的區間的資訊可以被合併成兩個區間的並區間的資訊」。即問題是可以被分解解決的。

對應單點更新模板、

void updata(int node,int l,int r,int ind,int add)    //

單結點更新、

int m = (l+r) >> 1

if(ind<=m) updata(node<<1

,l,m,ind,add);

else updata((node<<1)+1,m+1

,r,ind,add);

segtree[node]=min(segtree[node<<1],segtree[(node<<1)+1

]);}

//回溯的時候修改每個結點的最小值、

rmq 查詢區間最值下標、

#include#include

using

namespace

std;

#define maxn 100

#define maxind 256 //

線段樹節點個數

//構建線段樹,目的:得到m陣列.

void build(int node, int b, int e, int m, int

a)

}

//找出區間 [i, j] 上的最小值的索引

int query(int node, int b, int e, int m, int a, int i, int

j)

intmain()

;

build(

1, 0, sizeof(a)/sizeof(a[0])-1

, m, a);

cout

<1, 0, sizeof(a)/sizeof(a[0])-1, m, a, 0, 5)

0;

}

連續區間修改或單結點更新的動態查詢問題

#include #include 

using

namespace

std;

#define lson l , m , rt << 1

#define rson m + 1 , r , rt << 1 | 1

#define root 1 , n , 1

#define ll long long

const

int maxn = 111111

;

ll add[maxn

<<2

];

ll sum[maxn

<<2

];

void pushup(int

rt)

void pushdown(int rt,int

m)

}

void build(int l,int r,int

rt)

int m = (l + r) >> 1

;

build(lson);

build(rson);

pushup(rt);

}

void update(int l,int r,int c,int l,int r,int

rt)

pushdown(rt , r - l + 1

);

int m = (l + r) >> 1

;

if (l <=m) update(l , r , c , lson);

if (m pushup(rt);

}

ll query(

int l,int r,int l,int r,int

rt)

pushdown(rt , r - l + 1

);

int m = (l + r) >> 1

;

ll ret = 0

;

if (l <= m) ret +=query(l , r , lson);

if (m < r) ret +=query(l , r , rson);

return

ret;

}

intmain()

else

}

return

0;

}

線段樹 小整理

求區間和 ll sum maxn 2 儲存區間和 ll add maxn 2 懶惰標記 ll a maxn 用於輸入儲存資料求區間和的函式 void pushup int x 建立線段樹 void buildtree int l,int r,int rt int m l r 1 buildtree ...

線段樹入門整理

線段樹 interval tree 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。宣告 1 include2 include3 const int maxnode 2097152 4 const int max 1000003 5 struct noden...

線段樹入門 資料整理

c題題解,專題訓練一 講解線段樹從入門到高階 線段樹開闢的空間一般是需要儲存的資料的4倍。線段樹使用了二分的思想 我自己認為 把區域進行不斷的二分。她能把一些對於區間 或者線段 的修改 維護,從 o n 的時間複雜度變成 o logn 目前常見的模板中,大體有兩種形式 使用簡單陣列,在函式引數表表示...