/** * Segment Tree * Basic version, support point update (PU) and region query (RU). * Underlying is an array with 4*n size, where n is the length of input array. */publicclassBasicSegmentTree{privatestaticfinalintBASE=1;privatefinalint[]tree;/** * The length of input array. */privatefinalintsize;/** * Instantiate the segment tree. * @param nums the input array. */publicBasicSegmentTree(int[]nums){size=nums.length;tree=newint[4*size];build(nums,0,size-1,BASE);}/** * Replace item at k with val. * @param k the index to replace in input array. * @param val target value to replace with. */publicvoidupdate(intk,intval){doUpdate(k,val,0,size-1,BASE);}/** * Get the region sum between [left, right] inclusive. * @param left the left index of the region in input array, inclusive. * @param right the right index of the region in input array, inclusive. * @return the region sum. */publicintquery(intleft,intright){returndoQuery(left,right,0,size-1,BASE);}privatevoidbuild(int[]nums,intstart,intend,intindex){if(start==end){tree[index]=nums[start];return;}intmid=start+((end-start)>>1);build(nums,start,mid,2*index);build(nums,mid+1,end,2*index+1);pushUp(index);}privatevoidpushUp(intindex){tree[index]=tree[2*index]+tree[2*index+1];}privatevoiddoUpdate(intk,intval,intstart,intend,intindex){if(start==end){tree[index]=val;return;}intmid=start+((end-start)>>1);if(k<=mid){doUpdate(k,val,start,mid,2*index);}else{doUpdate(k,val,mid+1,end,2*index+1);}pushUp(index);}/** * Get the sum of target region [left, right] starting from current region [start, end]. * @param left target region left index, inclusive. * @param right target region right index, inclusive. * @param start current region left index, inclusive. * @param end current region right index, inclusive. * @param index current index of the segment tree. * @return the sum of target region. */privateintdoQuery(intleft,intright,intstart,intend,intindex){if(left<=start&&end<=right){returntree[index];}intsum=0;intmid=start+((end-start)>>1);/* * Case #1: only need to query left half of current region. * [left, right] * mid * Case #2: only need to query right half * [left, right] * mid * Case #3: query both left and right half * [left, right] * [start mid, mid+1 end] * Limitation: left <= right, start <= end * So, if left > mid, must have mid < left <= right, which is Case #2; * if right <= mid, must have left <= right <= mid, which is Case #1; * if left <= mid < right, which is Case #3. */if(left<=mid){sum+=doQuery(left,right,start,mid,2*index);}if(right>mid){sum+=doQuery(left,right,mid+1,end,2*index+1);}returnsum;}publicstaticvoidmain(String[]args){int[]a={10,11,12,13,14};BasicSegmentTreebst=newBasicSegmentTree(a);System.out.println("60 = "+bst.query(0,4));System.out.println("33 = "+bst.query(0,2));System.out.println("36 = "+bst.query(1,3));System.out.println("27 = "+bst.query(3,4));bst.update(2,15);System.out.println("63 = "+bst.query(0,4));System.out.println("36 = "+bst.query(0,2));System.out.println("39 = "+bst.query(1,3));System.out.println("27 = "+bst.query(3,4));}}
/** * Query the item at index of the input array. * @param index of the input array. * @return the item at index. */publicintpointQuery(intindex){returndoPointQuery(index,0,size-1,BASE);}privateintdoPointQuery(intwhere,intstart,intend,intindex){if(start==end){returntree[index];}intmid=start+((end-start)>>1);if(where<=mid){returndoPointQuery(where,start,mid,2*index);}else{returndoPointQuery(where,mid+1,end,2*index+1);}}
/** * Add x to all items between [left, right] inclusive. * @param left left index of the region. * @param right right index of the region. * @param x value to add. */publicvoidadd(intleft,intright,intx){if(x==0){return;}doAdd(left,right,x,0,size-1,BASE);}privatevoiddoAdd(intleft,intright,intx,intstart,intend,intindex){if(left<=start&&end<=right){tree[index]+=(end-start+1)*x;if(start!=end){lazy[index]+=x;}return;}intmid=start+((end-start)>>1);if(lazy[index]!=0){pushDown(start,mid,end,index);}if(left<=mid){doAdd(left,right,x,start,mid,2*index);}if(right>mid){doAdd(left,right,x,mid+1,end,2*index+1);}pushUp(index);}privatevoidpushDown(intstart,intmid,intend,intindex){tree[2*index]+=(mid-start+1)*lazy[index];lazy[2*index]+=lazy[index];tree[2*index+1]+=(end-mid)*lazy[index];lazy[2*index+1]+=lazy[index];lazy[index]=0;}
/** * Replace all items between [left, right] inclusive with val. * @param left left index of the region. * @param right right index of the region. * @param val value to replace */publicvoidupdate(intleft,intright,intval){doUpdate(left,right,val,0,size-1,BASE);}privatevoiddoUpdate(intleft,intright,intval,intstart,intend,intindex){if(left<=start&&end<=right){tree[index]=(end-start+1)*val;if(start!=end){lazy[index]=val;visited[index]=true;}return;}intmid=start+((end-start)>>1);if(visited[index]){pushDown(start,mid,end,index);}if(left<=mid){doAdd(left,right,val,start,mid,2*index);}if(right>mid){doAdd(left,right,val,mid+1,end,2*index+1);}pushUp(index);}privatevoidpushDown(intstart,intmid,intend,intindex){tree[2*index]=(mid-start+1)*lazy[index];lazy[2*index]=lazy[index];visited[2*index]=true;tree[2*index+1]=(end-mid)*lazy[index];lazy[2*index+1]=lazy[index];visited[2*index+1]=true;lazy[index]=0;visited[index]=false;}