洛谷題單指南-二叉堆與樹狀陣列-P3368 【模板】樹狀陣列 2

五月江城發表於2024-11-18

原題連結:https://www.luogu.com.cn/problem/P3368

題意解讀:樹狀陣列應用-區間修改,單點求值

解題思路:

設原陣列為s[N],其差分陣列為a[N]

操作一:區間修改

要對s[x] ~ s[y]每個數增加k,相當於對a[x]加k,對a[y + 1]減k,O(n)的操作變成了O(1)的操作,

利用樹狀陣列tr[N]的add(x, k), add(y + 1, -k)來實現對於a[N]的操作即可.

操作二:單點求值

要求s[x]的值,相當於求a[1] ~ a[x]所有數的和,

利用樹狀陣列的sum(x)求和即可。

樹狀陣列初始化:

初始化時,要對原陣列的值求差分,新增到樹狀陣列。

100分程式碼:

#include <bits/stdc++.h>
using namespace std;

const int N = 500005;
int n, m;
int s[N], tr[N];

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

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

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

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> s[i];
        add(i, s[i] - s[i - 1]); //構造差分的樹狀陣列
    }
    int op, x, y, k;
    while(m--)
    {
        cin >> op;
        if(op == 1)
        {
            cin >> x >> y >> k;
            add(x, k);
            add(y + 1, -k);
        }
        else if(op == 2)
        {
            cin >> x;
            cout << sum(x) << endl;
        }
    }
    return 0;
}

相關文章