• 差分数组


    今天学习了一下差分数组,觉得好神奇啊。

    1.定义:

    对于已知有n个元素的离线数列d,我们可以建立记录它每项与前一项差值的差分数组f:显然,f[1]=d[1]-0=d[1];对于整数i∈[2,n],我们让f[i]=d[i]-d[i-1]。

    2.简单性质:

    (1)计算数列各项的值:观察d[2]=f[1]+f[2]=d[1]+d[2]-d[1]=d[2]可知,数列第i项的值是可以用差分数组的前i项的和计算的,即d[i]=f[i]的前缀和,即d[i]=f[i]+f[i-1]+.....+f[1]。
    (2)计算数列每一项的前缀和:第i项的前缀和即为数列前i项的和,那么推导可知

    即可用差分数组求出数列前缀和;

    3.用途:

    (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];

    //修改区间,查询点
    #include<iostream>
    #include<cstring>
    #include <cstdio>
    using namespace std;
    const int maxn=100005;
    const int maxq=100005;
    int d[maxn];
    int f[maxn];
    int n,q;
    void update(int x,int y,int z)
    {
        f[x]+=z;
        f[y+1]-=z;
    }
    int sum(int x)
    {
        int ans=0;
        for(int i=1; i<=x; i++)
            ans+=f[i];
        return ans;
    }
    int main()
    {
        cin>>n;
        for(int i=1; i<=n; i++)
            cin>>d[i];
        f[1]=d[1];
        for(int i=2; i<=n; i++)
            f[i]=d[i]-d[i-1];
        cin>>q;
        while(q--)
        {
            int x;
            cin>>x;
            if(x==1)
            {
                int y,z,w;
                cin>>y>>z>>w;
                update(y,z,w);
            }
            if(x==2)
            {
                int y;
                cin>>y;
                cout<<sum(y)<<endl;
            }
        }
        return 0;
    }
    /*
    5
    1 2 3 4 5
    10
    1
    2 3 2
    2 3
    */
    
  • 相关阅读:
    Git上传文件、文件夹到github
    Git管理修改、撤销修改、删除文件
    Git使用教程之从远程库克隆项目(四)
    Git使用教程之在github上创建项目(三)
    Git使用教程之SSH连接方式配置(二)
    Git使用教程之新手也能看懂(一)
    JS字符串截取 “指定字符” 前面和后面的内容!
    vue.js 实现点击展开收起动画
    最简单的手机预览WEB移动端网页的方法
    vue-cli中浏览器图标的配置
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160173.html
Copyright © 2020-2023  润新知