洛谷 P3368——树状数组 / 树状数组模板题,区间修改,单点查询

洛谷 P3368——树状数组
树状数组可以进行单点修改和区间查询,这题要区间修改,要想办法把区间操作变为单点操作,于是想到差分。建树时把原数组的差分数组放入树状数组可以满足我们的要求。而要查询修改后单点 u 的值,可以把差分数组的 1 ~ u 加起来,这个和就是单点 u 的值。而差分数组的 1 ~ u 的和可以分解成 logn 个规模的 tr[] 的和,找到这些 tr[] 相加得到的和即为差分数组 1 ~ u 的和,即为原数组 u 的值。

#include <iostream>

using namespace std;

const int N = 5e5 + 10;

int n, m;
int a[N], tr[N];

int lowbit(int x)
{
    return x & -x;    
}

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

int sum(int u)
{
    // 差分数组的 1 ~ u 的和可以分解成 logn 个规模的 tr[] 的和,找到这些 tr[] 相加得到的和即为差分数组 1 ~ u 的和,即为原数组 u 的值。
    int ans = 0;
    for (int i = u; i > 0; i -= lowbit(i)) ans += tr[i];
    return ans;
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )  
    {
        cin >> a[i];
        add(i, a[i] - a[i - 1]);
    }
    
    while (m -- )
    {
        int type;
        cin >> type;
        
        if (type == 1) 
        {
            int x, y, c;
            cin >> x >> y >> c;
            
            add(x, c), add(y + 1, -c);
        }else
        {
            int u;
            cin >> u;
            cout << sum(u) << '\n';
        }
    }
    
    return 0;
}
posted @ 2023-04-26 15:52  妃即  阅读(38)  评论(0编辑  收藏  举报