一行N个方格,开始每个格子里的数都是0。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N≤100000,提问和修改的总数可能达到100000条。
20
6
M 1 1
M 2 2
M 3 4
M 3 -5
M 6 7
C 2 6
8
直接线段树的区间计数模板就好了
定义一个线段树,里面再定个参数vol,用于统计覆盖当前区间的线段数
#include<iostream>
#include<cstdio>
using namespace std;
struct Tree
{
int l, r, vol;
}tree[500000];
void Build(int x, int L, int R)
{
tree[x].l = L; tree[x].r = R;
int mid = (L + R) >> 1;
if (tree[x].l == tree[x].r) return ;
Build (x * 2, L, mid);
Build (x * 2 + 1, mid + 1, R);//这里要注意,和前面的不一样,mid要+1,因为是格子,不是点
}//建树
void Ins(int x, int pla, int num)
{
if (tree[x].l == pla && tree[x].r == pla) {
tree[x].vol += num;
return ;
}
if (pla <= tree[x * 2].r) Ins(x * 2, pla, num);
else Ins(x * 2 + 1, pla, num);
tree[x].vol = tree[x * 2].vol + tree[x * 2 + 1].vol;//通过左右儿子的值,算出父亲节点的值(因为左右儿子的值之和为父亲的值,而下面改变了,直接将上面的值覆盖掉就好了)
}
int Count(int x, int L, int R)
{
if (tree[x].l == L && tree[x].r == R)
return tree[x].vol;
if (R <= tree[x * 2].r) return Count (x * 2, L, R);
else if (L >= tree[x * 2 + 1].l) return Count (x * 2 + 1, L, R);
else
return Count(x * 2, L, tree[x * 2].r) + Count(x * 2 + 1, tree[x * 2 + 1].l, R);
}
int main()
{
char c;
int n, m, x, y;
scanf("%d", &n);
scanf("%d", &m);
Build(1, 1, n);
getchar();
for (int i = 1; i <= m; ++i)
{
c = getchar();
if (c == 'M') {
scanf("%d%d", &x, &y);
getchar();
Ins(1, x, y);
}
else {
scanf("%d%d", &x, &y);
getchar();
printf("%d\n", Count(1, x, y));
}
}
}