算法 | 预处理 | 区间加 | 询问区间和 |
---|---|---|---|
差分序列 | o(n) | o(1) | o(n) |
树状数组 | o(nlogn) | o(n) | o(1) |
线段树 | o(n) | o(n) | o(log n) |
线段树
不懂线段树的直接看b站大佬视频:https://www.bilibili.com/video/BV1cb411t7AM?from=search&seid=7095115582360789450
线段树标准代码
#include<stdio.h>
const int N=1e5+10;
int a[N],tree[4*N]={0};
// 查询区间[L,R]的区间数值之和
int query_tree(int node,int start,int end,int L,int R){
if(R<start||L>end) return 0;
else if(L<=start&&end<=R) return tree[node];
else if(start==end) return tree[node];
int mid=(start+end)/2;
int left_node=2*node+1,right_node=2*node+2;
int sum_left=query_tree(left_node,start,mid,L,R);
int sum_right=query_tree(right_node,mid+1,end,L,R);
return sum_left+sum_right;
}
// 把数组a的下标为 idx的值改为val
void update_tree(int node,int start,int end,int idx,int val){
if(start==end){
tree[node]=val;
return ;
}
int mid=(start+end)/2;
int left_node=2*node+1,right_node=2*node+2;
if(idx>=start&&idx<=mid) update_tree(left_node,start,mid,idx,val);
else update_tree(right_node,mid+1,end,idx,val);
tree[node]=tree[left_node]+tree[right_node];
}
//建树
void build_tree(int node,int start,int end){
if(start==end){
tree[node]=a[end];
return ;
}
int mid=(start+end)/2;
int left_node=2*node+1,right_node=2*node+2;
build_tree(left_node,start,mid);
build_tree(right_node,mid+1,end);
tree[node]=tree[left_node]+tree[right_node];
}
int main(){
int n,q,l,r;
scanf("%d%d",&n,&q);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
build_tree(0,0,n-1);
for(int i=0;i<q;i++){
scanf("%d%d",&l,&r);
printf("%d\n",query_tree(0,0,n-1,l,r));
}
}