一行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));
}
}
}