线段树就是区间的查找,如果区间不是当前线段树节点的区间,需要划分为左、右,再递归查找
#include <iostream> #include <stdio.h> #include <string> using namespace std; const int maxn = 55555; int a[maxn]; int tree[maxn << 2];//节点数是区间的4倍 void pushUp(int curr) { tree[curr] = tree[2*curr] + tree[2*curr+1]; } void buidTree(int left, int right, int curr) {//本节点在数组中的位置是curr;本节点的左边界是left,右边界是right if (left == right) { tree[curr] = a[left]; return; } int m = left + (right - left)/2; // if (m >= left) buidTree(left,m,2*curr); // if (m+1<=right) buidTree(m+1,right,2*curr + 1); pushUp(curr); } void update(int p, int add, int left, int right, int curr) {//第p个数,增加add;当前节点是curr,左是left,右是right;先找到p在哪个范围内,一定要找到精确的小范围,然后大范围是由小范围组合而成 if (left == right) { tree[curr] += add; return; } int m = left + (right - left)/2; if (p <= m) update(p,add,left,m,2*curr); else update(p,add,m+1,right,2*curr + 1); pushUp(curr); } int query(int ql, int qr, int currLeft, int currRight, int curr) {//查找区间[ql,qr] if (ql <= currLeft && qr >= currRight) { return tree[curr]; } int m = currLeft + (currRight - currLeft)/2; int sum = 0; if (ql <=m) sum = query(ql,qr,currLeft,m,2*curr); if (qr >m) sum += query(ql,qr,m+1,currRight,2*curr+1); return sum; } int main() { int t,n; scanf("%d", &t); for (int i = 0; i < t ; ++i ) { printf("Case %d:\n",i+1); scanf("%d",&n); memset(a,0,sizeof(a)); for (int j = 1; j <= n; ++j ) scanf("%d",a + j); buidTree(1,n,1); char op[10]; while(scanf("%s",&op)) { if (op[0] == 'E') break; int a1,a2; scanf("%d%d",&a1,&a2); if (op[0] == 'Q') printf("%d\n",query(a1,a2,1,n,1)); else if(op[0] == 'S') update(a1,-a2,1,n,1); else update(a1,a2,1,n,1); } } }
#include <iostream> #include <stdio.h> using namespace std; const int maxn = 55555; int a[maxn]; int tree[maxn<<2];//线段树的每一个叶子节点就是a中的元素,还有其他的非叶子节点,应该需要2*maxn+1个元素 void pushUp(int ind) { tree[ind] = tree[2*ind] + tree[2*ind+1]; } void buildTree(int left, int right, int ind) {//找到叶子节点相应的位置, ind是这个节点的编号//left 和 right是这个节点所对应的范围 if (left == right) { tree[ind] = a[left]; return; } int mid = (left + right)/2; buildTree(left, mid, 2*ind); buildTree(mid+1, right, 2*ind + 1); pushUp(ind); } int query(int beg, int end , int left, int right, int ind){// beg, end是要查询的区间;left和right是这个节点的范围 if (beg<=left && end >= right) return tree[ind]; int mid = (left + right) / 2; int l = 0, r = 0; if (mid >= beg) l = query(beg,end,left,mid, 2*ind); if (mid < end) r = query(beg,end,mid +1,right, 2*ind+1); return l+ r; } void update(int pos, int value, int left, int right, int ind) { if(left == right) { tree[ind] += value; return; } int mid = (left + right) / 2; if (mid >=pos) update(pos, value, left, mid, 2*ind); else update(pos,value, mid + 1, right, 2*ind+1); pushUp(ind); } int main() { int t,n; scanf("%d", &t); for (int i = 0; i < t ; ++i) { printf("Case %d:\n", i + 1); scanf("%d", &n); memset(a,0,sizeof(a)); for(int j = 1; j <= n; ++j) scanf("%d", a + j); buildTree(1,n, 1); char op[10]; while (scanf("%s", op)){ if (op[0] == 'E') break; int a1, a2; scanf("%d%d", &a1,&a2); if (op[0] == 'Q') printf("%d\n", query(a1, a2,1,n,1)); else if(op[0] == 'S') update(a1,-a2,1,n,1); else update(a1,a2,1,n,1); } } }