差分数组

    xiaoxiao2021-04-15  370

    差分数组


    假设有一个数组a[i],现在定义一个数组b[i], b[1] = a[1] 且: a [ i ] = b [ i ] − b [ i − 1 ] a[i] = b[i] - b[i - 1] a[i]=b[i]b[i1] ##简单性质 差分数组的性质就是,类似于微分。这样的话,假如 b[i] + c 会意味着 a[i] 以后的所有元素都会加上 c 假设我们需要将 [l,r] 区间内的 a 数组都加上一个 c ,那么我们只要给 b[l] 加上一个 c 给 b[r + 1] 减去一个 c 即可。 所以说这个差分的性质可以用来解决多次的对某个区间进行加减运算的题目

    (1)快速处理区间加减操作:

    假如现在对数列中区间[L,R]上的数加上x,我们通过性质(1)知道,第一个受影响的差分数组中的元素为f[L],即令f[L]+=x,那么后面数列元素在计算过程中都会加上x;最后一个受影响的差分数组中的元素为f[R],所以令f[R+1]-=x,即可保证不会影响到R以后数列元素的计算。这样我们不必对区间内每一个数进行处理,只需处理两个差分后的数即可;

    (2)询问区间和问题:

    由性质(2)我们可以计算出数列各项的前缀和数组sum各项的值;那么显然,区间[L,R]的和即为ans=sum[R]-sum[L-1];


    编程技巧

    一般在操作时会将原始数组先都假设为0,然后通过对[i,i]区间加上a[i]的 操作得到给定的a[i] (这个操作相当于对a数组的i元素加上a[i])


    例题

    输入一个长度为n的整数序列。

    接下来输入m个操作,每个操作包含三个整数l, r, c,表示将序列中[l,r]之间的每个数加上c。

    请你输出进行完所有操作后的序列。

    输入格式

    第一行包含两个整数n和m。

    第二行包含n个整数,表示整数序列。

    接下来m行,每行包含三个整数l,r,c,表示一个操作。

    输出格式

    共一行,包含n个整数,表示最终序列。

    数据范围

    $$ 1 \leq m,n \leq 10000 $$

    输入样例:

    6 3 1 2 2 1 2 1 1 3 1 3 5 1 1 6 1 输出样例: 3 4 5 3 4 2 #include <iostream> const int N = 100010; using namespace std; void insert(int l, int r, int c, int b[]) { b[l] += c; b[r + 1] -= c; } int main() { int n, m; scanf("%d %d", &n, &m); int a[n + 1] = {0}, b[n + 1] = {0}; //获取原始数组 但是第一次将原始数组a和差分数组b都全为0 for(int i = 1; i <= n; i++) scanf("%d", &a[i]); //对原始数组进行第一次操作 即对每个[i,i]区间加入a[i] 得到操作后的a[i] b[i] for(int i = 1; i <= n; i++) insert(i, i, a[i], b); while(m--) { int r, l, c; scanf("%d %d %d", &l, &r, &c); insert(l, r, c, b); } for(int i = 1; i <= n; i++) { b[i] += b[i - 1]; printf("%d ",b[i]); } return 0; }

    最新回复(0)