前缀和与差分数组

目录

一、前缀和

1、前缀和作用

2、一维前缀和代码

3、二维前缀和代码(容斥原理)

二、差分

1、差分作用

2、几种常见的差分

2、二维差分


一、前缀和

1、前缀和作用

降低查询时的时间复杂度。例如:有n个数a_i(i = 0,1,2,3...n),从i开始求和到j,即\sum_{i}^{j}a_i,如果暴力计算t个和的时间复杂度为O(n);采用前缀和计算,每次计算的为​​​​​​​b_j - b_{i-1},时间复杂度为O(1)

2、一维前缀和代码

for(int i = 1;i <= n;i ++){
    b[i] = b[i - 1] + a[i];
}

3、二维前缀和代码(容斥原理)

for(int i = 1;i <= n;i ++){
    for(int j = 1;j <= m;j ++){
        b[i][j] = b[i - 1][j] + b[i][j - 1] + a[i][j] - b[i - 1][j - 1];
    }
}

二、差分

1、差分作用

前缀和的逆运算,减轻数据间的不规律波动。例如:对数组中某一个区间递加num_i(i = 1,2...),可以先对这段区间求差分,再进行前缀和操作。

2、几种常见的差分

常数差分:

    int a[N],b[N];
    int l,r,k,n;
    scanf("%d%d%d%d",&l,&r,&k,&n);
    a[l] += k;
    a[r + 1] -= k;
    for(int i = 1;i <= n;i ++){
        b[i] = a[i] + b[i - 1];
    }   

等差数列差分:

    int a[N],b[N];
    int l,r,a0,d,n;
    scanf("%d%d%d%d%d",&l,&r,&a0,&d,&n);
    a[l] += a0;
    a[l + 1] += d - a0;
    a[r + 1] -= a0 + (r - l + 1)*d;
    a[r + 2] += a0 + (r - l)*d;
    for(int i = 1;i <= n;i ++){
        b[i] = b[i - 1] + a[i];
    }
    for(int i = 1;i <= n;i ++){
        b[i] = b[i - 1] + b[i];
    }

平方数列差分:

    int a[N],b[N];
    int l,r,a0,n;						//a0表示平方数列的第一项的开根
    scanf("%d%d%d%d",&l,&r,&a0,&n);
	a[l] += a0*a0;
    a[l + 1] += 2*a0 + 1 - 2*a0*a0;
    a[l + 2] += a0*a0 -2*a0;
    a[r + 1] += -(a0 + r - l)*(a0 + r - l) - 2*a0 - 2*(r - l);
    a[r + 2] += 2*(a0 + r - l)*(a0 + r - l) + 2*a0 + 2*(r - l) - 1;
	a[r + 3] += -(a0 + r - l)*(a0 + r - l);
	for(int i = 1;i <= n;i ++){
        b[i] = b[i - 1] + a[i];
    }
    for(int i = 1;i <= n;i ++){
        b[i] = b[i - 1] + b[i];
    }
	for(int i = 1;i <= n;i ++){
        b[i] = b[i - 1] + b[i];
    }

2、二维差分

常数差分:

    int a[N][N],b[N][N];
    int xl,,yl,xr,yr,k,n;
    scanf("%d%d%d%d%d%d",&xl,&xr,&yl,&yr,&k,&n);
    a[xl][yl] += k;a[xr + 1][yr + 1] += k;
    a[xl][yr + 1] -= k;a[xr + 1][yr] -= k;
    for(int i = 1;i <= n;i ++){
    for(int j = 1;j <= m;j ++){
        b[i][j] = b[i - 1][j] + b[i][j - 1] + a[i][j] - b[i - 1][j - 1];
    }
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Muly_cpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值