ACM入门之【线段树】
生活随笔
收集整理的這篇文章主要介紹了
ACM入门之【线段树】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
線段樹是算法競賽中常用的用來維護 區間信息 的數據結構。
線段樹可以在 O(logN)的時間復雜度內實現單點修改、區間修改、區間查詢(區間求和,求區間最大值,求區間最小值)等操作。
線段樹相對于樹狀數組代碼較長,但是線段樹較全面,功能性更強。
線段樹的基本分為兩類:
- 單點修改,不需要懶標記。
- pushup: 由子節點向上更新父節點
- bulild: 一段區間初始化成線段樹
- modify:修改
- query:查詢
- 區間修改,需要懶標記。
- pushup: 由子節點向上更新父節點
- pushdown: 由父節點向下更新子節點
- bulild: 一段區間初始化成線段樹
- modify:修改
- query:查詢
線段樹代碼實現的兩種方法:
- 結構體來實現,結構體內保存了各個信息。
- 數組來實現,則需要在寫線段樹函數的時候需要額外的維護信息。
線段樹需要開四倍的原因:
我們不難看出上圖的倒數第二行最多為n,那么上面就是n-1 那么最后一行最多為2*n 故總共最多為4*n-1
下面我們來具體的看一下線段樹代碼實現的兩種方法:
用結構體來實現線段樹:
數組實現線段樹:
#include<bits/stdc++.h> using namespace std; const int N=1e5*5+10; int a[N],f[N*4],n,m;//f[i]表示編號為i的區間的和 void build(int u,int l,int r) {if(l==r){f[u]=a[l];return;}int mid=l+r>>1;build(u*2,l,mid);build(u*2+1,mid+1,r);f[u]=f[u*2]+f[u*2+1]; } void add(int u,int l,int r,int x,int v) {f[u]+=v;if(l==r) return;int mid=l+r>>1;if(x<=mid) add(u*2,l,mid,x,v);else add(u*2+1,mid+1,r,x,v); } int query(int u,int l,int r,int l1,int r1) {if(l==l1&&r==r1) return f[u];int mid=l+r>>1;if(mid>=r1) return query(u*2,l,mid,l1,r1);else if(l1>=mid+1) return query(u*2+1,mid+1,r,l1,r1);else{int sum=0;sum+=query(u*2,l,mid,l1,mid);sum+=query(u*2+1,mid+1,r,mid+1,r1);return sum;} } int main(void) {cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=0;i<m;i++){int op; cin>>op;if(op==1){int x,k; cin>>x>>k;add(1,1,n,x,k);}else{int l,r; cin>>l>>r;cout<<query(1,1,n,l,r)<<endl;}}return 0; }總結
以上是生活随笔為你收集整理的ACM入门之【线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ACM入门之【树状数组】
- 下一篇: ACM入门之【线段树习题】