初学线段树--单点更新,区间查询
算法思路:运用递归,建完树之后,再通过递归,找到树节点的左区间端点==右区间端点&&等于你要查询的那个下标,然后更新其值,就完成了单点更新,最后区间查询时注意区间横跨树的两个节点的情况。
下面上代码:
#include<iostream> #include<cstdio> using namespace std; typedef struct Node { int value; int l; int r; }; Node tree[1000050*4]; int a[1000050]; int n,m; long int sum; char str[10]; void build_tree(int v,int l,int r) { tree[v].l=l; tree[v].r=r; if(l==r) { tree[v].value=a[l]; return; } else { int mid=(l+r)/2; build_tree(v*2,l,mid); build_tree(v*2+1,mid+1,r); tree[v].value=tree[v*2].value+tree[v*2+1].value; } } void query(int v,int l,int r) { if(tree[v].l==l&&tree[v].r==r) { sum+=tree[v].value; return; } int mid=(tree[v].l+tree[v].r)/2; if(r<=mid) { query(v*2,l,r); } else { if(l>mid) query(v*2+1,l,r); else { query(v*2,l,mid); query(v*2+1,mid+1,r); } } } void update(int v,int add,int p) { if(tree[v].l==tree[v].r) { tree[v].value+=add; return; } int mid=(tree[v].l+tree[v].r)/2; if(p<=mid) update(v*2,add,p); else update(v*2+1,add,p); tree[v].value=tree[v*2].value+tree[v*2+1].value; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } build_tree(1,1,n); for(int i=0;i<m;i++) { int left=0,right=0; sum=0; scanf("%s%d%d",str,&left,&right); if(str[0]=='Q') { query(1,left,right); printf("%d\n",sum); } else { int p=left; int add=right; update(1,add,p); } } return 0; }