洛谷 P2068 统计和 - 树状数组
洛谷 P2068 统计和
题目链接:洛谷 P2068 统计和
算法标签: 树状数组
题目
题目描述
给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=10000)个问题,求每段区间的和。时间限制1秒。
输入格式
第一行1个数,表示序列的长度n
第二行1个数,表示操作的次数w
后面依次是w行,分别表示加入和询问操作
其中,加入用x表示,询问用y表示
x的格式为"x a b" 表示在序列a的位置加上b
y的格式为"y a b" 表示询问a到b区间的加和
一个整数ans,即最少操作次数。
输出格式
每行一个数,分别是每次询问的结果
输入输出样例
输入 #1
5
4
x 3 8
y 1 3
x 4 9
y 3 4
输出 #1
8
17
题解:
树状数组
脱光光的树状数组,真的出了区间查询之外,没有啥啊???
那么如果只会单点查找和,不会查找区间怎么办???
——那,前缀和会嘛???
没错啊,树状数组实现维护区间和就是把两个单点和减一下,像不像维护完前缀和再求区间和?
int ans = getsum(b) - getsum(a - 1);
就是这么个东西\(QwQ\)
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1;
int n, m, tree[N];
void update(int x, int val)
{
for (int i = x; i <= n; i += i & -i)
tree[i] += val;
}
int getsum(int x)
{
int res = 0;
for (int i = x; i; i -= i & -i)
res += tree[i];
return res;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++ )
{
char ch[10];
int a, b;
scanf("%s%d%d", ch, &a, &b);
if (ch[0] == 'x')
{
update(a, b);
continue ;
}
else if (ch[0] == 'y')
{
int ans = getsum(b) - getsum(a - 1);
printf("%d\n", ans);
continue ;
}
}
return 0;
}