洛谷 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;
}
posted @ 2019-11-12 14:56  筱柒_Littleseven  阅读(110)  评论(0编辑  收藏  举报