差分与前缀和模板题(蓝桥杯 C++ 题目 注解)

目录

[题目一(大学树木要打药 差分):](#题目一(大学树木要打药 差分):)

代码:

[题目二(小明的彩灯 差分):](#题目二(小明的彩灯 差分):)

代码:

[题目三(区间更新 差分):](#题目三(区间更新 差分):)

代码:

[题目四(劳动课作业 差分):](#题目四(劳动课作业 差分):)

​​​​​代码:

[题目五(大学里的树木要维护 前缀和):](#题目五(大学里的树木要维护 前缀和):)

代码:

[题目六(积木大厦 前缀和):](#题目六(积木大厦 前缀和):)

代码:

差分和前缀和是常用的数列处理技巧,可以在一维数组或二维数组中快速求解某一区间的和或区间中每个元素的差值。差分可以将原始数列转化为差分数列,而前缀和可以用来求解原始数列中某一区间的和。

差分(Difference): 对于一维数组a,定义差分数组di = ai - ai-1 (i > 0),其中d0 = a0。差分数组d是通过相邻元素的差值得到的,可以用来表示原始数列a中的元素变化情况。例如,对于数组a = 5, 3, 7, 2, 1,其差分数组d = 5, -2, 4, -5, -1。

前缀和(Prefix Sum): 对于一维数组a,定义前缀和数组si = Σaj (0 <= j <= i),其中s0 = a0。前缀和数组s是通过累计相邻元素的和得到的,可以用来表示原始数列a中某一位置之前的元素和。例如,对于数组a = 5, 3, 7, 2, 1,其前缀和数组s = 5, 8, 15, 17, 18。

差分和前缀和的应用:

  1. 求解某一区间的和:对于差分数组d,要求解原始数组a中l, r区间的和,只需计算前缀和数组s在该区间的差值,即sr - sl-1。
  2. 求解某一位置的元素值:对于差分数组d,要求解原始数组a中位置i的元素值,只需计算前缀和数组s在该位置的值,即si。
  3. 更新某一区间的值:对于差分数组d,要更新原始数组a中l, r区间的值,只需将差分数组d在该区间内的元素都加上相应的增量。

差分和前缀和的时间复杂度均为O(n),其中n为数组的长度。差分和前缀和常用于解决区间求和、区间更新等问题,能够优化算法的效率。

题目一(大学树木要打药 差分):

代码:

cpp 复制代码
#include<iostream>
#include<cstring>
using namespace std;
int n, m;
int a[1000010];
int main()
{
    cin >> n >> m;
    memset(a, 0, sizeof(a));//初始都为0
    for (int i = 0; i < m; i++)//运用差分思想进行操作
    {
        int l, r, v;
        cin >> l >> r >> v;
        a[l] += v;
        a[r + 1] -= v;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)//前缀和还原
    {
        a[i] += a[i - 1];
        ans += a[i];
    }
    cout << ans;
}

题目二(小明的彩灯 差分):

代码:

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
long long a[100010];
long long b[100010];//差分数组
int main()
{
  int n,q;
  cin>>n>>q;
  memset(a,0,sizeof(a));
  for(int i=1;i<=n;i++)//差分
  {
       cin>>a[i];
       b[i] = a[i]- a[i-1];
  }
  while(q--)//操作
  {
    int l,r,x;
    cin>>l>>r>>x;
    b[l]+=x;
    b[r+1]-=x;
  }

  for(int i=1;i<=n;i++)
  {
    b[i] += b[i-1];
    if(b[i]<0)
    {
      cout<<0<<" ";
    }
    else
    cout<<b[i]<<" ";
  }
}

题目三(区间更新 差分):

代码:

cpp 复制代码
#include <iostream>
using namespace std;
long long a[100010],n,m;
long long cha[100010];//差分数组
int main()
{
  while(cin>>n>>m)
  {
    for(int i=1;i<=n;i++)//差分
    {
      cin>>a[i];
      cha[i]=a[i]-a[i-1];
    }
    while(m--)//操作
    {
      int l,r,x;
      cin>>l>>r>>x;
      cha[l]+=x,cha[r+1]-=x;
    }
    for(int i=1;i<=n;i++)//合并
    {
        cha[i]+=cha[i-1];
        cout<<cha[i]<<" ";
    }
    cout<<endl;
  }
}

题目四(劳动课作业 差分):

​​​​​代码:

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
long long a[10000010], n, m;
int main()
{
    cin >> n >> m;
    memset(a, 0, sizeof(a));
    while (m--)
    {
        int l, r;
        cin >> l >> r;
        a[l] += 1;
        a[r + 1] -= 1;
    }
    for (int i = 1; i <= n; i++)
    {
        a[i] += a[i - 1];
        cout << a[i] << " ";
    }
}

题目五(大学里的树木要维护 前缀和):

代码:

cpp 复制代码
#include<iostream>
using namespace std;
int n,m;
int a[100010];
int sum[100010];
int main()
{
  cin>>n>>m;
  for(int i=1;i<=n;i++)
  {
       cin>>a[i];
       sum[i]=a[i]+sum[i-1];//前缀和
  } 
  for(int i=1;i<=m;i++)
  {
    int l,r;
    cin>>l>>r;
    cout<<sum[r]-sum[l-1]<<endl;
  }
}

题目六(积木大厦 前缀和):

代码:

cpp 复制代码
#include <iostream>//如1、2、3、4、5,其实只要这五项的和大于15就可以形成递增
using namespace std;
long long a[100010];
long long sum[100010];
long long sums=0;
int main()
{
  int n;
  cin>>n;
  for(int i=1;i<=n;i++)
  {
    cin>>a[i];
    sum[i]=sum[i-1]+a[i];
    sums+=i;
  }
  if(sum[n]>=sums)
  cout<<"YES";
  else
  cout<<"NO";

}
相关推荐
CV爱数码5 分钟前
CT 重建从零开始(五):ASTRA Toolbox 上手——几何、投影器与算法
图像处理·算法·计算机视觉·ct
fpcc11 分钟前
计算机原理—如何高效的操作文件
c++·计算机原理
Rabitebla33 分钟前
【系统性学习笔记】Linux 权限篇(二):文件属性、权限修改与目录权限的底层逻辑
linux·c++·笔记·学习·算法
system_error_x40 分钟前
C++ 编程基础入门教程
开发语言·c++
远离UE41 小时前
半拉格朗日学习笔记 动力学 实时渲染
人工智能·算法
小郎君6581 小时前
MPTT 不是万能编号:一棵百万节点树的增删改与批量事务
算法
FPGA小徐1 小时前
【一生一芯 / PA】AM 核心文件逐行解析(上):从 start.S 到 gpu.c
前端·算法
Tairitsu_H2 小时前
[动态规划#1] 子数组 | 最大子数组和 | 环形子数组的最大和 | 乘积最大子数组 | 乘积为正数的最长子数组
算法·动态规划
凯瑟琳.奥古斯特2 小时前
动态调优IoU提升OCR文本合并精度
开发语言·python·算法
布莱克6053 小时前
A* 算法详解:从原理到实现
开发语言·c++·算法