http://acm.hdu.edu.cn/showproblem.php?pid=1166
需求:
1.点修改
2.区间求和
标准的BIT(二叉索引树,又名树状数组)问题,当然也可以用最基础的仅支持“点修改”的线段树来解决!
1.线段树版本:
#include <cstdio> #include <iostream> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 65536 + 5; // 65536 是最小的大于等于50000的2^k, 这里如果写成50000 + 5 可是要超时的! int sumv[MAXN*2-1]; int n, N; int ql, qr; int query(int o, int l, int r) { if(qr < l || r < ql) return 0; if(ql <= l && r <= qr) return sumv[o]; int m = (l + r) >> 1, ret = 0; ret += query((o << 1) + 1, l, m); ret += query((o << 1) + 2, m + 1, r); return ret; } void update(int k, int v) { k += N-1; sumv[k] = v; while(k>0) { k = (k-1) >> 1; sumv[k] = sumv[(k << 1) + 1] + sumv[(k << 1) + 2]; } } char s[20]; int main () { int T, p, q, v; scanf("%d", &T); for(int kase = 1; kase <= T; kase++) { scanf("%d", &n); N = 1; while(N < n) N <<= 1; // 找到最小的大于等于n的2^k,因为叶子节点至少要放得下n个数字 int tot = (1<<N)-1; for(int i=0; i<tot; i++) sumv[i] = 0; // 初始化 // 构建线段树 O(nlgn) // for(int i=0; i<n; i++) { // scanf("%d", &v); // update(i, v); // } // 构建线段树 O(n) for(int i=0; i<n; i++) { scanf("%d", &sumv[N-1+i]); } for(int i=N-2; i>=0; i--) { sumv[i] = sumv[(i << 1) + 1] + sumv[(i << 1) + 2]; } printf("Case %d:\n", kase); while(scanf("%s", s) != EOF && s[0] != 'E') { scanf("%d%d", &p, &q); if(s[0] == 'A') { update(p-1, sumv[p-1+N-1] + q); } else if(s[0] == 'S') { update(p-1, sumv[p-1+N-1] - q); } else { ql = p-1; qr = q-1; printf("%d\n", query(0, 0, N-1)); } } } return 0; }
2.树状数组(BIT)版本:
#include <cstdio> #include <iostream> #include <cstring> #include <string> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 50000 + 5; int C[MAXN]; char s[20]; int n; int query(int x) { int ret = 0; while(x) { ret += C[x]; x -= x&(-x); } return ret; } void add(int k, int d) { while(k <= n) { C[k] += d; k += k&(-k); } } int main () { int T, p, q, x; scanf("%d", &T); for(int kase = 1; kase <= T; kase++) { scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &x); add(i, x); } printf("Case %d:\n", kase); while(scanf("%s", s) != EOF && s[0] != 'E') { scanf("%d%d", &p, &q); if(s[0] == 'A') { add(p, q); } else if(s[0] == 'S') { add(p, -q); } else { printf("%d\n", query(q) - query(p-1)); } } memset(C, 0, sizeof(C)); } return 0; }