線段樹和樹狀陣列的功能類似 但是比樹狀陣列強大的是線段樹求逆序對線段樹可以進行區間的更新操作(不只是單點更新
如把陣列1-3加5 或者把陣列5-6全部改為4 等等
但是線段樹的**量比樹狀陣列要大
記住線段樹的記憶體是普通的四倍!!!
下面**
線段樹輸入乙個陣列
改變區間l到r 使a陣列l到r每個加上d
求區間ll到rr的和
樣例:10
1 2 3 4 5 6 7 8 9 10
5 7 2
1 8
輸出42
*/#include#include#include#include#include#includeusing namespace std;
int w[1000];
struct nodea[1000];
void pushdown(int p)
}void build(int l,int r,int p)
if(lmid 代表右
if(r<=mid) return query(l,r,2*p); //只用往左子樹找 遞迴呼叫的時候查詢區間不變
else if(l>mid) return query(l,r,2*p+1); //只用往右子樹找 遞迴呼叫的時候查詢區間不變
else return query(l,mid,2*p)+query(mid+1,r,2*p+1); //兩邊都找}/*
更新區間 如果更新乙個區間 那麼從根到這個區間的值都要改變 此時的耗時太大
所以增加乙個addv的域
每次要計算區間 就把sum的值加上 (r-l+1)*addv 如果已經計算過這個結點就不用往下算sum
直接return就可以了 這樣就可以減少計算次數
*/void update(int l,int r,int p,int d)
int mid=(a[p].left+a[p].right)/2;
pushdown(p);//傳addv的值
if(r<=mid) update(l,r,2*p,d);
else if(l>mid) update(l,r,2*p+1,d);
else
a[p].sum=a[2*p].sum+a[2*p+1].sum;//算完子節點後再更新sum
}int main()
#include #include #include #define max 51000
#define mid(a,b) (a+b)>>1
#define r(a) (a<<1|1)
#define l(a) a<<1
typedef struct node;
int ans[max];
node tree[max<<2];
int n;
void build(int t,int l,int r) //以1為根節點建立線段樹
mid=mid(tree[t].left,tree[t].right);
build(l(t),l,mid);
build(r(t),mid+1,r);
}void insert(int t,int l,int r,int x) //向以1為根節點的區間[l,r]插入數字1
mid=mid(tree[t].left,tree[t].right);
if(l>mid)
else if(r<=mid)
else
tree[t].num=tree[l(t)].num+tree[r(t)].num;
}int query(int t,int l,int r) //查詢以1為根節點,區間[l,r]的和
else if(r<=mid)
else
}int main()
for(i=1,k=0;i<=n;i++)
printf("%lld\n",k);
}return 0;
}
筆記 線段樹
一顆二叉樹,即為t a,b 引數a,b表示該節點表示區間 a,b 區間長度b a記為l。遞迴定義t a,b 若區間長度l 1 區間 a a b2 a,a b 2 為t的左兒子,區間 a b2 1,b a b2 1,b 為t的右兒子。若區間長度l 1 t為乙個葉子結點,表示區間 a 葉結點為區間內的所...
線段樹學習筆記
線段樹是一種 二叉搜尋樹 與區間樹 相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度為o logn 而未優化的 空間複雜度 為2n,因此有時需要離散化讓空間壓縮。以下筆記摘自lcomyn神犇部落格 1....
線段樹學習筆記
本文筆記在參考一步一步理解線段樹 tenos的基礎上形成 線段樹,也是二叉搜尋樹的一種,是基於陣列,但是優於陣列的一種資料結構。同時結合預處理 時間複雜度一般在o n 使得從原來陣列的o n 的查詢和更新複雜度降到了o logn 在處理很大資料量的資料更新和查詢最值方面變得簡單,值得一提的是,它的構...