推薦前輩學姐博客文章,寫的很細html
http://www.javashuo.com/article/p-ddxbfjfo-dk.htmlnode
學學半,此隨筆主要是加深本身對線段樹的理解數組
題目:洛谷P3374模(mu)板題ui
(話說爲何是樹狀數組,主要是由於我太菜了不會懶標記)spa
//代碼中的位運算其實就是乘除2的一些操做
#include<cstdio> using namespace std; int n,m,ans; struct node { int left,right,num; }tree[500000*4+5];//經典的四倍空間,我也不知道爲何 int input[500000+5]; void build(int index,int l,int r)//建樹,一棵滿二叉樹 { tree[index].left=l,tree[index].right=r; if(l==r) { tree[index].num=input[l]; return ; } int mid=(l+r)>>1; build(index<<1,l,mid);build(index<<1|1,mid+1,r); tree[index].num=tree[index<<1].num+tree[index<<1|1].num; } void add(int index,int target,int k)//單點修改,變量是序號、目標、修改值 { tree[index].num+=k;//對於每一個能夠遞歸到的點都是包含目標target這個點的集合,都要一併加上k if(tree[index].left==tree[index].right)//單點集合返回 return ; if(target<=tree[index<<1].right) add(index<<1,target,k); if(target>=tree[index<<1|1].left) add(index<<1|1,target,k);//兩個if語句都是判斷是否存在交集,是則進行下一層 } void query(int index,int l,int r)//區間求和(區間查詢) { if(tree[index].right<=r&&tree[index].left>=l) { ans+=tree[index].num;//對於區間的子集累計答案 return ;//避免累計區間子集的區間子集 ??exm } if(tree[index].right==tree[index].left) return ; if(tree[index<<1].right>=l) query(index<<1,l,r); if(tree[index<<1|1].left<=r) query(index<<1|1,l,r);//同爲尋找交集 return ; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",input+i); build(1,1,n);//建樹 for(int i=1,a,x,y;i<=m;i++) { scanf("%d%d%d",&a,&x,&y); if(a==1) add(1,x,y);//單點修改 if(a==2) { ans=0; query(1,x,y);//區間查詢 printf("%d\n",ans); } }
return 0; }
等改天問一下學長們懶標記的具體code