线段树 P3374 【单点修改 区间查询】
题目
https://www.luogu.com.cn/problem/P3374
代码
树状数组版:
#include<iostream> #include<cstdio> using namespace std; long long a[500001], c[500001]; int n, m; int lowbit(int x) { return x&(-x); } void update(int i, int k) { while (i <= n) { c[i] += k; i += lowbit(i); } } long long getsum(int i) { long long res = 0; while (i > 0) { res += c[i]; i -= lowbit(i); } return res; } int main() { int aa, bb, cc; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); update(i, a[i]); } for (int i = 0; i < m; i++) { scanf("%d%d%d", &aa, &bb, &cc); if (aa == 1) update(bb, cc); else printf("%lld\n", getsum(cc) - getsum(bb - 1)); } }
线段树版:
#include<iostream> #include<cstdio> using namespace std; int n, m; long long a[500001], c[500001*4]; void build(int l, int r, int k) { if (l == r) c[k] = a[l]; else { int mid = (l + r) >> 1; build(l, mid, k << 1); build(mid + 1, r, k << 1 | 1); c[k] = c[k << 1] + c[k << 1 | 1]; } } void update(int index, int v, int l, int r, int k) { if (l == r) a[l]+=v,c[k] += v; else { int mid = (l + r) >> 1; if (mid >= index) update(index, v, l, mid, k << 1); else update(index, v, mid + 1, r, k << 1 | 1); c[k] = c[k << 1] + c[k << 1 | 1]; } } long long query(int L, int R, int l, int r, int k) { if (L <= l&&R >= r) return c[k]; else { long long res = 0; int mid = (l + r) >> 1; if (L <= mid) res += query(L, R, l, mid, k << 1); if (R > mid) res += query(L, R, mid + 1, r, k << 1 | 1); return res; } } int main() { int aa, bb, cc; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); build(1, n, 1); for (int i = 0; i < m; i++) { scanf("%d%d%d", &aa, &bb, &cc); if (aa == 1) update(bb,cc,1,n, 1); else printf("%lld\n", query(bb,cc,1,n,1)); } }