050.等差数列差分

等差数列

  • 首项 s
  • 末项 e
  • 共差 d

等差数列差分

在区间[l,r]上加上一个等差数列

知道了区间长度,根据 e - s = d * (r - l)

对于s,e,d我们可以知二求三

对于原始数组a[]={0,0,0,0,0,0,0}

[1,4]加上一个等差数列s=5,d=2,e=11

我们希望得到{0,5,7,9,11,0,0}

对结果求一次差分逆过程a[i]-=a[i-1]

得到{0,5,2,2,2,-11,0}

再求一次差分逆过程a[i]-=a[i-1]

得到{0,5,-3,0,0,-13,11}

我们发现中间的若干项都变成0了,我们只需要修改4个位置

0,0,0 , s , d-s , 0,0,0,0,0,0,0,0,0 , -d-e , e , 0,0,0,0

最后进行两次累加更新即可

void change(int l,int r,int s,int d,int e){
    d[l]+=s;
    d[l+1]+=d-s;
    d[r+1]+=-d-e;
    d[r+2]+=e;
}
void update(int n){
    for(int _=0;_<2;_++){
        for(int i=1;i<=n;++i){
            a[i]+=a[i-1];
        }
    }
}

习题

luogu P4231

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e7+5;
ll a[N]={0};
void change(int l,int r,ll s,ll d,ll e){
    a[l]+=s;
    a[l+1]+=d-s;
    a[r+1]+=-d-e;
    a[r+2]+=e;
}
void update(int n){
    for(int k=0;k<2;++k){
        for(int i=1;i<n;++i){
            a[i]+=a[i-1];
        }
    }
}
void solve(){
    int n,m,l,r;
    ll s,e,d;
    cin>>n>>m;
    while(m--){
        cin>>l>>r>>s>>e;
        d=(e-s)/(r-l);
        change(l-1,r-1,s,d,e);
    }
    update(n);
    ll ans1=0,ans2=-1;
    for(int i=0;i<n;++i){
        ans1^=a[i];
        if(a[i]>ans2)ans2=a[i];
    }
    cout<<ans1<<' '<<ans2;
}
int main(void){
    cin.tie(0)->sync_with_stdio(0);
    int T=1;
    //cin>>T;
    while(T--)solve();
}

luogu P5026

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=2e6+5;
const int offset=300005;
//为了保证差分的正确性,超出边界的位置也要处理,整体添加一个偏移量
ll a[N];
int n,m,v,x;
void change(int l,int r,int s,int d,int e){
    a[l]+=s;
    a[l+1]+=d-s;
    a[r+1]+=-d-e;
    a[r+2]+=e;
}
void update(int n){
    for(int _=0;_<2;++_){
        for(int i=1;i<=n+offset;++i){
            a[i]+=a[i-1];
        }
    }
}
void solve(){
    cin>>m>>n;
    while(m--){
        cin>>v>>x;
        x+=offset;
        change(x-3*v+1,x-2*v,1,1,v);
        change(x-2*v+1,x,v-1,-1,-v);
        change(x+1,x+2*v,1-v,1,v);
        change(x+2*v+1,x+3*v-1,v-1,-1,1);
    }
    update(n);
    for(int i=1;i<=n;++i){
        cout<<a[i+offset]<<' ';
    }
}
int main(void){
    cin.tie(0)->sync_with_stdio(0);
    int T=1;
    //cin>>T;
    while(T--)solve();
}
posted @ 2026-01-18 11:28  射杀百头  阅读(2)  评论(0)    收藏  举报