前缀和与差分

前缀和与差分是一对关联性十分强的两个算法,都是对一段数组进行操作,一个是累加,一个是两两相减,话不多说上干货!!!

前缀和

前缀和分一维和二维两种,这里我主要分析二维的,一维的比较简单;

以以前写的代码展开详细描述与解释,并附上题目

cpp 复制代码
int main() 
{
    int n,m,q;
    cin>>n>>m>>q;
    vector<vector<int>> arr(n+1,vector<int>(m+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>arr[i][j];
        }
    }
    vector<vector<long long>> ret(n+1,vector<long long>(m+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            ret[i][j]=ret[i-1][j]+ret[i][j-1]+arr[i][j]-ret[i-1][j-1];
        }
    }
    int x1,x2,y1,y2;
    while(q--)
    {
        cin>>x1>>y1>>x2>>y2;
        cout<<ret[x2][y2]-ret[x1-1][y2]-ret[x2][y1-1]+ret[x1-1][y1-1]<<endl;
    }
    return 0;
}

i,j为例,若以i,j为例,retij的值为以1,1为左上角到以i,j为右下角中所有位置的和;但是若一直使用for循环从左上角遍历到右下角进行累加,那时间复杂度太高了,不可取;所以我们应该复用之前的位置进行计算;分为两种情况,一种是求整块的面积;一种是求阴影部分的面积

  • 求阴影部分的面积

在计算此阴影部分的面积,我们应该利用x1-1,y2x2,y1-1x1-1,y1-1这三个点;因为以x1-1,y2x2,y1-1位置为右下角的两个部分有重叠部分,多减的部分要加回来,即以x1-1,y1-1为右下角部分面积,由此我们可以推出公式:

S阴影=retx2y2-retx1-1y2-retx2y1-1+retx1-1y1-1

  • 求整块的面积

在计算此阴影部分的面积,我们应该利用x-1,yx,y-1x-1,y-1x,y这四个点;因为以x-1,yx,y-1位置为右下角的两个部分有重叠部分,多加的部分要减回来,即以x-1,y-1为右下角部分面积,最后,还需要加上原数组中的右下角的元素x,y,由此我们可以推出公式:

retxy=retx-1y+retxy-1-retx-1y-1+arrxy

注:以上虽然是模板,但是因为变量较多,不建议背诵,需要大家私底下自己画图推导,方为上策!!!

差分

差分分为一维与二维,与前缀和不同,差分这个概念我们比较陌生,所以,应该我会把一维与二维都详细推导一遍;

以以前写的代码展开详细描述与解释,并附上题目

  • 一维差分
cpp 复制代码
typedef long long ll;
const int N = 5e5 + 10;
ll f[N];//差分数组

int main()
{
    int n, q;
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        f[i] += x;
        f[i + 1] -= x;
    }
    while (q--)
    {
        ll l, r, k;
        cin >> l >> r >> k;
        f[l] += k;
        f[r + 1] -= k;
    }
    for (int i = 1; i <= n; i++)
    {
        f[i] = f[i - 1] + f[i];
        cout << f[i] << " ";
    }
    return 0;
}

一维差分介绍:一维差分 是一种用于高效处理数组区间更新与查询 的技巧,其核心思想是通过构造一个差分数组,将对原数组的区间批量修改 操作转化为差分数组的单点修改 ,从而将时间复杂度从 O(n) 优化到 O(1),常与前缀和配合使用

  • 具体过程如下

差分数组初始化:d1=a1di=ai−ai−1(2≤i≤n)​

  • 二维差分
cpp 复制代码
typedef long long LL;
const int N=1010;
int n,m,q;
LL f[N][N];

void insert(int x1,int y1,int x2,int y2,LL k)
{
    f[x1][y1]+=k;f[x1][y2+1]-=k;f[x2+1][y1]-=k;f[x2+1][y2+1]+=k;
}

int main()
{
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int x;cin>>x;
            insert(i,j,i,j,x);
        }
    }
    while(q--)
    {
        int a,b,c,d,k;cin>>a>>b>>c>>d>>k;
        insert(a,b,c,d,k);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+f[i][j];
            cout<<f[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

二维差分介绍:二维差分是一维差分的扩展,用于高效处理二维数组的矩形区域批量更新,核心目标是将矩形区域的加 / 减操作从 O(nm) 的时间复杂度优化为 O(1),常与二维前缀和配合使用,广泛应用于矩阵区间修改、图像处理等场景

  • 具体过程如下

初始化差分数组

操作二维数组

优化

  • 综合练习------借教室

这是一道综合二分和差分和前缀和的综合题,有助于提升大家可以写写看

题目连接:https://www.luogu.com.cn/problem/P1083

cpp 复制代码
const int N=1e6+10;
int f[N],r[N];
int d[N],s[N],t[N];
int n,m;

//1到x天的订单情况
bool check(int x)
{
    //初始化整个差分数组
    for(int i=1;i<=n;i++)
        f[i]=r[i]-r[i-1];
    //在对应区间减去教室数
    //对应的
    for(int i=1;i<=x;i++)
    {
        f[s[i]]-=d[i];
        f[t[i]+1]+=d[i];
    }
    //还原整个数组数组
    for(int i=1;i<=n;i++)
    {
        f[i]=f[i-1]+f[i];
        if(f[i]<0) return false;
    }
    return true;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>r[i];
    for(int i=1;i<=m;i++) cin>>d[i]>>s[i]>>t[i];
    int l=1,r=m;
    while(l<r)
    {
        int mid=(l+r)/2;
        if(check(mid)) l=mid+1;
        else r=mid;
    }
    //判断结果这个点
    if(check(l)) cout<<0<<endl;
    else cout<<-1<<endl<<l<<endl;;
    return 0;
}
相关推荐
南境十里·墨染春水3 小时前
C++ 工厂模式:从入门到进阶,彻底掌握对象创建的艺术
开发语言·c++·算法
@insist1233 小时前
系统架构设计师-实时性评价、调度算法与内核架构选型
算法·架构·系统架构·软考·系统架构设计师·软件水平考试
一只齐刘海的猫9 小时前
【Leetcode】找到字符串中所有字母异位词
算法·leetcode·职场和发展
海清河晏1119 小时前
数据结构 | 八大排序
数据结构·算法·排序算法
IronMurphy10 小时前
【算法五十七】146. LRU 缓存
算法·缓存
凌波粒11 小时前
LeetCode--108.将有序数组转换为二叉搜索树(二叉树)
算法·leetcode·职场和发展
liulilittle11 小时前
KCC:在 BBR 思路上的一次探索
网络·tcp/ip·算法·bbr·通信·拥塞控制·kcc
浦信仿真大讲堂11 小时前
达索系统SIMULIA Abaqus 2026接触和约束的增强新功能介绍
人工智能·python·算法·仿真软件·达索软件
点云侠11 小时前
PCL 生成三棱锥点云
c++·算法·最小二乘法