本题利用线段树求区间和。
用build(int k,int l,int r)构建二叉线段树。k代表节点序号,l,r分别是区间左右。
递归构建左右子树(随即更新节点的区间和),递归结束的条件为节点区间的左右相等时即为叶节点。
用search(int k,int l,int r)查找区间和。k代表该节点。l,r是要查询区间和的左右端,当要查找的区间的左端大于该节点的中点时,递归查找该节点的右子树,当要查找的区间的右端小于等于中点时,递归查找该节点的左子树。当左端小于等于中点且右端大于中点时,则把递归查找左子树和右子树并把两者的区间和加起来。递归结束的条件为当前k节点的区间左右分别和要查找的区间相等。
#include <bits/stdc++.h>
#define maxn 1000000*4+50
using namespace std;
struct node{
int l,r,sum;
}t[maxn];
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
if(t[k].l==t[k].r){
scanf("%d",&t[k].sum);//cin>>t[k].sum;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
}
int search(int k,int l,int r){
if(t[k].l==l&&t[k].r==r)
return t[k].sum;
int mid=(t[k].l+t[k].r)>>1;
if(mid>=r)
search(k<<1,l,r);
else if(mid<l)
search(k<<1|1,l,r);
else
return search(k<<1,l,mid)+search(k<<1|1,mid+1,r);
}
int main(){
int n,m,l,r;
scanf("%d %d",&n,&m);//cin>>n>>m;
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d %d",&l,&r);//cin>>l>>r;
printf("%d\n",search(1,l,r));//cout<<search(1,l,r)<<endl;
}
}