AcWing算法提高课-4.2.2一个简单的整数问题

宣传一下算法提高课整理 <—

csdn

题目传送门点这里

题目描述

给定长度为 N N N 的数列 A A A,然后输入 M M M 行操作指令。

第一类指令形如 C l r d,表示把数列中第 l ∼ r l∼r lr 个数都加 d d d

第二类指令形如 Q x,表示询问数列中第 x x x 个数的值。

对于每个询问,输出一个整数表示答案。

输入格式

第一行包含两个整数 N N N M M M

第二行包含 N N N 个整数 A [ i ] A[i] A[i]

接下来 M M M 行表示 M M M 条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

1 ≤ N , M ≤ 1 0 5 , 1≤N,M≤10^5, 1N,M105,
∣ d ∣ ≤ 10000 , |d|≤10000, d10000,
∣ A [ i ] ∣ ≤ 1 0 9 |A[i]|≤10^9 A[i]109

样例输入

10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2

样例输出

4
1
2
5

思路

这是一道模板题,操作为区间修改,单点查询
普通的树状数组处理的是单点修改,区间查询

所以我们将原数组进行一次差分,再将差分数组加到树状数组内。

这样,原本树状数组询问的 1 1 1 ~ x x x 的前缀和,就转变为了求 x x x 的值;原本树状数组将一个点加c的操作就转变为了将区间加c。

算法时间复杂度

树状数组每次操作都是 O ( log ⁡ n ) O(\log n) O(logn) 的复杂度,一共 m m m 次查询

所以时间复杂度大约是 O ( m log ⁡ n ) O(m \log n) O(mlogn)

AC Code

C + + C++ C++

#include <iostream>
#include <cstring>

using namespace std;

const int N = 100010;

int n, m;
int a[N], b[N]; // a是原数组,b是差分数组
int tr[N]; // 树状数组

int lowbit(int x) // 树状数组模板
{
	return x & -x;
}

void add(int x, int c)
{
	for (int i = x; i <= n; i += lowbit(i))
		tr[i] += c;
}

int sum(int x)
{
	int res = 0;
	for (int i = x; i; i -= lowbit(i))
		res += tr[i];
	return res;
}

int main()
{
	int l, r, d, x;
	string op;
	
	cin >> n >> m;
	for (int i = 1; i <= n; i ++ )
	{
		scanf("%d", &a[i]);
		b[i] = a[i] - a[i - 1]; // 将原数组变为差分数组
		add(i, b[i]); // 将差分数组加入树状数组
	}
	
	while (m -- )
	{
		cin >> op; // 读入操作
		if (op[0] == 'C')
		{
			scanf("%d%d%d", &l, &r, &d);
			add(l, d); add(r + 1, -d); 
			// 第一种情况:区间修改,这是差分的基本操作,将b[l]加c,b[r+1]减c
		}
		if (op[0] == 'Q')
		{
			scanf("%d", &x);
			int res = sum(x);
			printf("%d\n", res);
			// 第二种情况:单点查询,相当于求差分数组的前缀和
		}
	}
	
	return 0;
}

a

最后,如果觉得对您有帮助的话,点个赞再走吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星河依旧长明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值