【ACWing】242. 一个简单的整数问题

题目地址:

https://www.acwing.com/problem/content/description/248/

给定长度为 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

考虑用树状数组维护其差分数组 d d d,那么预处理部分相当于将第 i i i个数加上 x x x,在差分数组里对应着 d [ i ] d[i] d[i]加上 x x x d [ i + 1 ] d[i+1] d[i+1]减去 x x x。将第 l ∼ r l\sim r lr里每个数加上 x x x,对应着 d [ l ] d[l] d[l]加上 x x x d [ r + 1 ] d[r+1] d[r+1]减去 x x x;求第 k k k个数的值,等价于求 d d d里前 k k k个数的和。代码如下:

#include <iostream>
using namespace std;

const int N = 1e5 + 10;
int n, m, tr[N];

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

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

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

int main() {
    
    
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
    
    
        int x;
        scanf("%d", &x);
        add(i, x);
        add(i + 1, -x);
    }

    while (m--) {
    
    
        char op[2];
        scanf("%s", op);

        int x;
        if (*op == 'Q') {
    
    
            scanf("%d", &x);
            printf("%d\n", sum(x));
        } else {
    
    
            int l, r;
            scanf("%d%d%d", &l, &r, &x);
            add(l, x);
			add(r + 1, -x);
        }
    }

    return 0;
}

预处理时间 O ( n log ⁡ n ) O(n\log n) O(nlogn),每次操作时间复杂度 O ( log ⁡ n ) O(\log n) O(logn),空间 O ( n ) O(n) O(n)

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/121474585