前缀 和 差分 数

本文详细介绍了前缀和和差分在数组操作中的应用,包括单维数组的前缀和计算、范围和的快速获取,以及二维矩阵的前缀和构建。同时,讲解了如何利用差分数组实现范围内的数加减操作,以及构造b数组的方法。两种技术在时间复杂度上均为O(1),是高效解决特定问题的工具。
摘要由CSDN通过智能技术生成

前缀和差分主要用于在一段范围内的数组中进行加减操作

在数组a[n]中,其前缀和数组s[n]

s[n]=s[n-1]+a[n]

特别注意!!!s[0]一定要空出来,s[n]初始化一定要从1开始,防止数组越界

例:求n个数中在[l,r]中的和

const int N = 1000010;
int a[N];
int s[N];

int main()

{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        s[i] = s[i - 1] + a[i];                     //构造s[n]数组
    int r, l;
    cin >> l >> r;
    cout << s[r] - s[l-1];                        //再求某范围的和时,左边的范围要-1
    return 0;    
}

二维前缀和

s[n][m]为长为n,宽为m的矩阵全部加起来的数

s[n][m]-s[n-1][m]-s[n][m-1]+s[n-1][m-1]=a[n][m]

注意防止数组越界问题!!!!!

const int N = 10010;
int a[N][N];
int s[N][N];

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];    //构造前缀和矩阵

    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    cout << s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];//注意求和时需要在左下和右上的坐标-1
    return 0;
    }

差分:

公式:a[n]=b[1]+b[2]+b[3]……+b[n]

           b[n]=a[n]-a[n-1]

           ***如果需要a[n]数组中在[l,r]这个范围中每个数都加c***

           只需要在b[l]+c,b[r]-c

           当b[l]+c,则a[l]到a[n]的每个数都加上c

           当b[r+1]-c,则a[r+1]到a[n]每个数都减c

           则实现范围[l,r]中每个a数组中的数都+c

那么如何构造b数组呢?我们可以自己先写一个函数

        void insert(int l,int r,int c)

   {

        b[l]+=c;

        b[r+1]-=c;

   }

这个函数可以用于   1.构造b数组

                                2.实现a数组在[l,r]范围内+c

一,构造b数组

for(int i=1;i<n;i++)

{

       insert(i,i,a[i]);

}

二,实现a数组在[l,r]范围内+c

insert(l,r,c);//得到处理完毕的b数组

for(int i=1;i<=n;i++)

{

       b[i]+=b[]i-1     //每一项依次累加将b数转为a数组

                             //被转化的b数组为已经在范围[l,r]每一项+c的a数组

}

总结!!!!

1.无论是前缀和还是差分都可以先把a[n]与s[n]或a[n]与b[n]的关系给列出来

2.根据关系创建s[n]/b[n]

3.s[n]可用于求a[n]任意范围内的和,b[n]可用于使a[n]任意范围内加减某个数

其时间复杂度都为0(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值