统计和
题目描述
给定一个长度为 n ( n ≤ 100000 ) n(n\leq 100000) n(n≤100000),初始值都为 0 0 0 的序列, x ( x ≤ 100000 ) x(x\leq 100000) x(x≤100000) 次的修改某些位置上的数字,每次加上一个数,然后提出 y ( y ≤ 100000 ) y(y\leq 100000) y(y≤100000) 个问题,求每段区间的和。
输入格式
第一行 1 1 1 个整数,表示序列的长度 n n n。
第二行 1 1 1 个整数,表示操作的次数 w w w。
后面依次是 w w w 行,分别表示加入和询问操作。
其中,加入用 x
表示,询问用 y
表示。
x x x的格式为 x a b
表示在序列上第 a a a 个数加上 b b b。保证 1 ≤ a ≤ n 1 \leq a \leq n 1≤a≤n, 1 ≤ b ≤ 1 0 9 1 \leq b \leq 10^9 1≤b≤109。
y y y 的格式为 y a b
表示询问 a a a 到 b b b 区间的加和。保证 1 ≤ a ≤ b ≤ n 1 \leq a \leq b \leq n 1≤a≤b≤n。
输出格式
每行一个正整数,分别是每次询问的结果
样例 #1
样例输入 #1
5
4
x 3 8
y 1 3
x 4 9
y 3 4
样例输出 #1
8
17
代码
#include <stdio.h>
int lowbit(int x); // 返回x的最低位的1对应的值
void update(int x, int v, int n); // 更新操作,将第x个位置加上v
long long getsum(int x); // 查询前x个数的和
#define MAXN 100010
long long c[MAXN]; // 树状数组int main() {int n, w, x, y;char op[2];scanf("%d %d", &n, &w); // 序列长度和操作次数while(w--){scanf("%s %d %d", op, &x, &y);if(op[0] == 'x'){update(x, y, n);}else{printf("%lld\n", getsum(y) - getsum(x - 1));}}return 0;
}int lowbit(int x) // 返回x的最低位的1对应的值
{return x & -x;
}void update(int x, int v, int n) // 更新操作,将第x个位置加上v
{for(int i = x; i <= n; i += lowbit(i)){c[i] += v;}
}long long getsum(int x) // 查询前x个数的和
{long long sum = 0;for(int i = x; i > 0; i -= lowbit(i)){sum += c[i];}return sum;
}