迪庆藏族自治州网站建设_网站建设公司_模板建站_seo优化
2026/1/18 11:29:39 网站建设 项目流程

等差数列

  • 首项 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();
}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询