【题目链接】
ybt 1547:【 例 1】区间和
【题目考点】
1. 线段树
2. 树状数组
【解题思路】
本题要求维护区间和,实现单点修改、区间查询。
解法1:线段树
线段树原理,及实现方法见:洛谷 P3374 【模板】树状数组 1(线段树解法)
解法2:树状数组
本题也可以使用树状数组完成,知识点及实现方法见:洛谷 P3374 【模板】树状数组 1(树状数组解法)。
由于都是模板题,大同小异,本文不再进行详细解释。
【题解代码】
解法1:线段树
#include<bits/stdc++.h>
using namespace std;
#define N 100005
struct Node
{int l, r, m;long long val;
} tree[4*N];
int n, m;
void pushUp(int i)
{tree[i].val = tree[2*i].val+tree[2*i+1].val;
}
void build(int i, int l, int r)
{tree[i].l = l, tree[i].r = r, tree[i].m = (l+r)/2;if(l == r){tree[i].val = 0;return;}build(2*i, l, tree[i].m);build(2*i+1, tree[i].m+1, r);pushUp(i);
}
void update(int i, int x, int v)//a[x] += v
{if(tree[i].l == tree[i].r){tree[i].val += v;return;}if(x <= tree[i].m)update(2*i, x, v);elseupdate(2*i+1, x, v);pushUp(i);
}
long long query(int i, int l, int r)
{if(l <= tree[i].l && tree[i].r <= r)return tree[i].val;long long s = 0;if(l <= tree[i].m)s += query(2*i, l, r);if(r > tree[i].m)s += query(2*i+1, l, r);return s;
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int k, x, y;cin >> n >> m;build(1, 1, n);while(m--){cin >> k >> x >> y;if(k == 0)update(1, x, y);elsecout << query(1, x, y) << '\n';}return 0;
}
解法2:树状数组
#include <bits/stdc++.h>
using namespace std;
#define N 100005
long long tree[N], n, m;//tree:树状数组
int lowbit(int x)
{return x & -x;
}
void update(int i, long long v)//a[i] += v 单点修改
{for(int x = i; x <= n; x += lowbit(x))tree[x] += v;
}
long long sum(int i)//求a[1]+...+a[i] 区间查询
{long long s = 0;for(int x = i; x > 0; x -= lowbit(x))s += tree[x];return s;
}
long long query(int l, int r)//求a序列区间和[l, r]
{return sum(r)-sum(l-1);
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);long long a, k, b;cin >> n >> m;for(int i = 1; i <= m; ++i){cin >> k >> a >> b;if(k == 0)update(a, b);elsecout << query(a, b) << '\n'; }return 0;
}