線段樹是一種數據結構……有了線段樹,咱們就能夠對一個序列進行快速修改並查詢某個區間內的最大值、最小值、和等……下面我來講一下線段樹是如何實現的ios
線段樹就是一棵二叉樹,咱們對一棵二叉樹上的點依次編號,從根節點開始,咱們從1開始編號,而後對於每一層的點從左到右編號,這樣咱們不難發現有一個很重要的性質,就是對於任意一個非葉子節點,他的左兒子的編號必定是這個節點乘2,右兒子就是這個節點的編號乘2加1。數據結構
我對於每個節點中儲存這個節點的全部的兒子節點的最大值、最小值、和,那麼咱們就必定能夠在log(n)的時間內對於要修改的點進行更新,或者對於某個區間進行查詢。ui
線段樹一開始確定感受有點亂,但最主要的仍是看看代碼,好好研究一下代碼是怎麼寫的,而後慢慢理解……我是在學了C++半年以後纔開始學線段樹的……我一開始反正沒懂……spa
代買以下(這就是對於一個序列的點修改和區間查詢的代碼):code
1 #include<iostream> 2 #define maxn 1000000 3 #define INF 2000000000 4 using namespace std; 5 int a[maxn],maxv[3*maxn],minv[3*maxn],sumv[3*maxn]; 6 void build(int L,int R,int o) 7 { 8 if(L==R)maxv[o]=minv[o]=sumv[o]=a[L]; 9 else 10 { 11 int m=L+(R-L)/2,lc=o<<1,rc=lc+1; 12 build(L,m,lc); 13 build(m+1,R,rc); 14 maxv[o]=max(maxv[lc],maxv[rc]); 15 minv[o]=min(minv[lc],minv[rc]); 16 sumv[o]=sumv[lc]+sumv[rc]; 17 } 18 return; 19 } 20 int x,v; 21 void update(int L,int R,int o) 22 { 23 if(L==R)maxv[o]=minv[o]=sumv[o]=v; 24 else 25 { 26 int m=L+(R-L)/2,lc=o<<1,rc=lc+1; 27 if(x<=m)update(L,m,lc); 28 if(x>m)update(m+1,R,rc); 29 maxv[o]=max(maxv[lc],maxv[rc]); 30 minv[o]=min(minv[lc],minv[rc]); 31 sumv[o]=sumv[lc]+sumv[rc]; 32 } 33 } 34 int ql,qr,_max,_min,_sum; 35 void query(int L,int R,int o) 36 { 37 if(ql<=L&&R<=qr) 38 { 39 _max=max(_max,maxv[o]); 40 _min=min(_min,minv[o]); 41 _sum+=sumv[o]; 42 } 43 else 44 { 45 int m=L+(R-L)/2,lc=o<<1,rc=lc+1; 46 if(ql<=m)query(L,m,lc); 47 if(qr>m)query(m+1,R,rc); 48 } 49 return; 50 } 51 int main() 52 { 53 int n,Q; 54 scanf("%d",&n); 55 for(int i=1;i<=n;i++) 56 { 57 scanf("%d",&a[i]); 58 } 59 build(1,n,1); 60 scanf("%d",&Q); 61 while(Q--) 62 { 63 char t; 64 scanf("%s",&t); 65 if(t=='Q') 66 { 67 _sum=0; 68 _min=-1u>>1; 69 _max=1<<31; 70 scanf("%d%d",&ql,&qr); 71 query(1,n,1); 72 printf("MaxNum: %d, MinNum: %d, Sum: %d\n",_max,_min,_sum); 73 } 74 if(t=='C') 75 { 76 scanf("%d%d",&x,&v); 77 update(1,n,1); 78 } 79 } 80 }