给定一个整数数组(下标由 0 到 n-1,其中 n 表示数组的规模),以及一个查询列表。每一个查询列表有两个整数[start, end]
。 对于每个查询,计算出数组中从下标 start 到 end 之间的数的总和,并返回在结果列表中。
样例
对于数组 [1,2,7,8,5]
,查询[(1,2),(0,4),(2,4)]
, 返回 [9,23,20]
这道题和上一篇文章:利用线段树解决区间最小值问题,非常相似,只是线段树中的区间最小值min改为区间的和val。仅在求和函数getsum和查询函数query发生了变化。
/**
* Definition of Interval:
* classs Interval {
* int start, end;
* Interval(int start, int end) {
* this->start = start;
* this->end = end;
* }
*/
class Solution {
struct segmentTreeNode{
int start,end;
long long val;
segmentTreeNode *left,*right;
segmentTreeNode(int l,int r):
start(l),end(r),left(0),right(0){}
};
segmentTreeNode* build(int lo,int hi){
if(lo>hi) return NULL;
segmentTreeNode* root=new segmentTreeNode(lo,hi);
if(lo==hi) return root;
int mid=lo+(hi-lo)/2;
root->left=build(lo,mid);
root->right=build(mid+1,hi);
return root;
}
void getsum(segmentTreeNode *root,int i,int value){
if(root->start==root->end){
root->val=value;
return;
}
int mid=root->start+(root->end-root->start)/2;
if(i<=mid) getsum(root->left,i,value);
else getsum(root->right,i,value);
root->val=root->left->val+root->right->val;
return;
}
long long query(segmentTreeNode*root,int low,int high){
if(low>high) return 0;
if(low==root->start&&high==root->end){
return (long long)root->val;
}
int mid=root->start+(root->end-root->start)/2;
long long res=query(root->left,low,min(mid,high))+query(root->right,max(low,mid+1),high);
return res;
}
public:
/**
*@param A, queries: Given an integer array and an query list
*@return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
// write your code here
int n=A.size(),m=queries.size();
vector<long long>res;
if(n==0||m==0) return res;
segmentTreeNode*root=build(0,n-1);
for(int i=0;i<n;i++) getsum(root,i,A[i]);
for(int i=0;i<m;i++){
Interval q=queries[i];
long long tmp=query(root,q.start,q.end);
res.push_back(tmp);
}
return res;
}
};