1.一维数组的前缀和
思路:
利用前缀和的算法,定义出一个新的数组prefix去存储每个区间的和,方便查询的结果,复杂度为O(1),然后结合前缀和的性质,进行区间的计算,如下,
sum[1,k]+sum[k+1,n]=sum[1,n]
//相当于区间的加和,由上边的等式,就可以推算出求前缀和区间的公式
ans=P[r] - P[l-1]
题解代码如下:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int N=1e5 + 10;
int a[N],prefix[N];
void solve()
{
int n,q;
cin>> n >> q;
for(int i=1;i<=n; ++i)cin>>a[i];
for(int i=1;i<=n ; ++i)prefix[i]=prefix[i-1]+a[i];
while(q--)
{
int l,r;
cin>> l >> r;
cout<< prefix[r] - prefix[l-1]<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--)
solve();
return 0;
}
2.一维数组的差分数组
思路:
对于题目的要求,我们可以利用差分数组来解决问题。
差分:对于一个数组a[],我们有一个数组diff[i]=a[i]-a[i-1],来存储,
同时可以进行后缀区间的修改,例如要对[l,r]区间进行修改,那么就是对 diff[l] 进行修改,这样会使得 a[l] 以后的所有数都参与了修改,这时候再对右端点修改 diff[r+1] 修改,就可以将 a[r+1] 之后的数组恢复原状,实现定位区间来修改的目的。下边是题解的代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define INF 0x3f3f3f3f
const int N=1e5 + 20;
// 开数组
int a[N],prefix[N],diff[N];
void solve()
{
int n,p,q;
cin>> n >> p >> q;
for(int i=1 ; i<=n ; i++)cin>>a[i];
for(int i=1 ; i <= n ; i++)diff[i]=a[i]-a[i-1];
while(p--)
{
int l,r,x;
cin>> l >> r >> x;
diff[l]+=x; diff[r+1]-=x;//对差分数组进行操作以达到区间修改的目的
}
for(int i=1; i <= n; i++) a[i]=a[i-1]+diff[i];
for(int i=1; i <= n; i++) prefix[i]=prefix[i-1]+a[i];
while(q--)
{
int l,r; cin>> l >> r ;
cout<<prefix[r]-prefix[l-1]<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t=1;
while(t--)
solve();
return 0;
}
以上题集来自于starrycoding网站