差分数组与前缀和

匿名 (未验证) 提交于 2019-12-02 23:48:02
  1. 前缀和
    前缀和顾名思义就是前面i个数的总和。
    假设有一个序列A,前缀和为S。根据概念很容易知到公式
    \(S[i]=\displaystyle \sum_{j=1}^iA[j]\)

    如何求区间\([l,r]\)的和呢?
    \(sum[l,r]=s[r]-s[l-1]\)

    那如果要对多个不同区间

    \([l,r]\)进行加减操作呢?然后输出某个区间\([l,r]\)的区间和,接下来就要用到差分数组了

  2. 差分数组

    设原数组为\(A[i]\),差分数组为\(B[i]\),则:

    \[B[i]=\begin{cases} A[i]&i=1\\ A[i]-A[i-1]&i\geq2 \end{cases}\]

    差分数组的性质:

    • 如果对区间\([l,r]\)进行修改,只需修改\(B[l],B[r+1]\)(\(B[l]\)加上修改值,\(B[r+1]\)减去修改值)

    • \(A[i]=\displaystyle \sum_{j=1}^{i}B[j]\)(通过\(B[i]=A[i]-A[i-1]\)证明)

    • $S[x]=\displaystyle \sum_{i=1}^{x}A[i]=\displaystyle \sum_{i=1}^{x} \displaystyle \sum_{j=1}^{i}B[j]=\displaystyle \sum _{i=1}^{x}(x-i+1)*B[i] $


有n个数。m个操作,每一次操作,将x~y区间的所有数增加z;

最后有q个询问,每一次询问求出x~y的区间和。

设原数组为\(A[i]\)

步骤:

  • 先求出差分数组\(B[i]=A[i]-A[i-1]\)
  • 在根据\(m\)个造作修改\(B[i]\)
  • 求修改后的\(A[i]=A[i-1]+B[i]\)
  • 求前缀和\(S[i]=S[i-1]+A[i]\)
  • 最后输出区间和\(sum[x,y]=S[y]-S[x-1]\)

举个栗子 航班预订统计

这道题很简单,没有要求输出区间和,也不用先求出差分数组

#include<iostream> using namespace std; int n;  //n个航班 int i;  //i条预定记录 int b[20005];   //差分数组  int main() {     cin>>n>>i;     for(int j=0;j<i;j++)     {         int x,y,z;  //[x,y]预定了z个座位         cin>>x>>y>>z;         b[x]+=z;         b[y+1]-=z;     }     for(int k=1;k<=n;k++)     {         b[i]+=b[i-1];         cout<<b[i]<<' ';     }      }

前面都是一维前缀和,再举个一位前缀和的栗子 最大子矩阵

没有涉及区间修改,只是求前缀和

#include<iostream> #include<algorithm> using namespace std; int m,n;    //整数矩阵 int x,y;    //所求子矩阵的长和宽 int b[1000][1000]; int ans;  int main() {     cin>>m>>n>>x>>y;     int t;     for(int i=1;i<=m;i++)         for(int j=1;j<=n;j++)         {             cin>>t;             b[i][j]+=b[i-1][j]+b[i][j-1]+b[i-1][j-1]+t;             if(i>=x&&j>=y)                 ans=max(ans,b[i][j]-b[i-x][j]-b[i][j-y]-b[i-x][j-y]);                         }     cout<<ans<<endl; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!