GDUT寒假训练场5-树状数组2

这篇博客介绍了如何利用差分和前缀和数据结构来高效地处理区间数值加法操作和单点查询。通过构建差分序列并存储前缀和,可以快速响应区间加法更新和查询请求,确保在大规模数据下保持高效率。文章提供了参考代码示例,展示了C++实现的详细过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某区间每一个数数加上 x;

  2. 求出某一个数的值。

输入格式

第一行包含两个整数 N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含  个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。

接下来 M 行每行包含 2 或 4个整数,表示一个操作,具体如下:

操作 1: 格式:1 x y k 含义:将区间 [x,y]内每个数加上k;

操作 2: 格式:2 x 含义:输出第 x 个数的值。

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

输入样例

5 5
1 5 4 2 3
1 2 4 2
2 3
1 1 5 -1
1 3 5 7
2 4

输出样例

6
10

数据规模

1≤N,M≤500000,1≤x,y≤n,保证任意时刻序列中任意元素的绝对值都不大于 2^30。

参考思路

我们构建差分,然后将差分都存进sum数组里面,形成一个前缀和数组,当询问时直接输出树状sum数组1-i 之和即可。

参考代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<sstream>
#include<string>
#include<map>
using namespace std;
typedef long long ll;
int dx[4] = { 0, 0, 1, -1 };
int dy[4] = { 1, -1, 0, 0 };
#define fo(i,l,r) for (int i = l; i <= r; ++i)
#define F 1500005
int n, m, a[F], sum[F], k, x, y, j;
int C(int x)
{
    return x & (-x);
}
void add(int x, int k)
{
    while (x <= n)
    {
        sum[x] += k;
        x = x + C(x);
    }
}
int ask(int x)
{
    int ans = 0;
    while (x > 0)
    {
        ans += sum[x];
        x -= C(x);
    }
    return ans;
}
int main()
{
    int t;
    cin >> n >> m;
    int last = 0;
    fo(i, 1, n)//构建差分序列之前缀和 用来维护区间加 求单点值
    {
        scanf("%d", &t); add(i, t - last); last = t;
    }

    while (m--)
    {
        scanf("%d", &j);
        if (j == 1)
        {
            scanf("%d%d%d", &x, &y, &k); add(x, k); add(y + 1, -k);
        }
        else
        {
            scanf("%d", &x);
            cout << ask(x) << endl;
        }
    }
    return 0;
}

>>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值