acwing差分

#include<iostream>
using namespace std;
const int N=100005;
int num[N],diff[N];
int main()
{
    int n,m;
    num[0]=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>num[i];
        
    }
    for(int i=1;i<=n;i++)
    {
        diff[i]=num[i]-num[i-1];
    }
    int l,r,c;
    for(int q=1;q<=m;q++) 
    {
        cin>>l>>r>>c;
        diff[l]+=c;
        diff[r+1]-=c;
    }
for(int i=1;i<=n;i++)
{
    diff[i]+=diff[i-1];
    
}
for(int i=1;i<=n;i++) 
{
    cout<<diff[i]<<" ";
    
}
cout<<endl;
}

acwing平台上,一维差分是一个重要的算法知识点,可高效处理数组区间操作问题。 一维差分是前缀和的逆运算,其核心是将数组上的“区间操作”转化为差分数组上的“单点操作”。具体而言,将数组`arr`的区间`[l, r]`加上一个值`v`,等价于将差分数组中的`d[l] + v`,再将`d[r + 1] - v`,最终时间复杂度为$O(n + m)$ [^4]。 以下是几个相关代码示例及解释: ### 代码示例一 ```cpp #include <bits/stdc++.h> using namespace std; const int N=1e5+5; int a[N]; //Primitive array int d[N]; //Difference array int main() { int n,m; cin>>n>>m; for(int i=1; i<=n; i++) { //i from 1 cin>>a[i]; d[i]=a[i]-a[i-1]; //Building a difference array } int le,ri,c; while(m--) { cin>>le>>ri>>c; d[le]+=c; d[ri+1]-=c; } for(int i=1; i<=n; i++) { //i from 1 a[i]=d[i]+a[i-1]; cout<<a[i]<<" "; } return 0; } ``` 此代码先构建差分矩阵,通过输入的`n`和`m`确定数组规模和操作次数。接着,根据输入的数组元素构建差分数组。在每次操作中,更新差分数组。最后,根据差分数组还原原数组并输出 [^1]。 ### 代码示例二 ```cpp #include<bits/stdc++.h> #define x first #define y second using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PII; const int N=1e5+5; int n,m; int a[N],b[N]; // a:原序列,b:差分序列 int s[N]; // 对b求前缀和 int l,r,c; int main() { cin>>n>>m; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=a[i]-a[i-1]; // 前缀和和差分下标都从1开始,否则容易有边界问题 } while(m--) { scanf("%d%d%d",&l,&r,&c); b[l]+=c; b[r+1]-=c; } // 用新数组s计算差分序列b的前缀和 for(int i=1;i<=n;i++) { s[i]=s[i-1]+b[i]; printf("%d ",s[i]); } cout<<endl; // 用累加的思想,在差分序列本身上做前缀和,节省空间 for(int i=1;i<=n;i++) { b[i]+=b[i-1]; printf("%d ",b[i]); } return 0; } ``` 该代码同样构建差分矩阵,使用`scanf`读取输入。在操作过程中更新差分数组,之后通过两种方式根据差分数组还原原数组:一种是用新数组`s`计算前缀和,另一种是在差分序列本身上做前缀和,节省空间 [^2]。 ### 代码示例三 ```cpp #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+10; int a[maxn]; int b[maxn];//构建差分数组 void abc(int l,int r,int c) { b[l]+=c; b[r+1]-=c; } int main() { int n,m,l,r,c; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); abc(i,i,a[i]);//构建差分数组; } while(m--) { scanf("%d%d%d",&l,&r,&c); abc(l,r,c); } for(int i=1;i<=n;i++) { a[i]=a[i-1]+b[i]; printf("%d ",a[i]); } return 0; } ``` 此代码通过函数`abc`封装区间操作,先根据输入元素构建差分数组,在操作时调用`abc`函数更新差分数组,最后还原原数组并输出 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值