传送门
思路:二次求前缀和
区间问题转化为求前缀和问题。
相减一定要先加Mod再余Mod
第一次;sum[i]-sum[i-1]=t[i];
sum[j]-sum[l-1];
sum[j+1]-sum[l-1];
...
sum[r]-sum[l-1];
相加在一起可归结为
sum[j]+sum[j+1]+sum[j+2]+...sum[r]-(l-r+1)*sum[l-1]
对 sum[j]+sum[j+1]+sum[j+2]+...sum[r] 再求一次前缀和
sum2[i]-sum2[i-1]=sum[i];
/*#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<cctype>
#include<stack>
#include<map>
#include<string>
#include<cstdlib>
#define ll long long
#define N 100010
#define rep(i,n) for(int i=0;i<(n);i++)
const int maxn = 10;
int a[maxn][maxn], b[maxn][maxn];
*/
#include<bits/stdc++.h>
const int mod=1000000007;
long long t[100005], sum[100005], sum2[100005];
using namespace std;
int main() {
//ll n, m, p, q;
ios::sync_with_stdio(false);
long long n, m, i, j;
cin >> n;
for(i = 1; i <= n; i++)
cin >> t[i];
long long ans = 0;
long long u, v;
for(i = 1; i <= n; i++)
sum[i] = (sum[i - 1] + t[i])%mod; //t[i]=sum[i]-sum[i-1]//第一次前缀和
//for(i = 1; i <= n; i++)
//sum2
for(i = 1;i <= n;i++)
sum2[i]=(sum2[i-1]+sum[i])%mod;//再求一次sum的前缀和
long long q,l,r;
cin >> q;
for(i = 0; i < q; i++) {
cin >> l >> r;
ans=(ans+((sum2[r]-sum2[l-1]+mod)%mod-(r-l+1)*sum[l-1]%mod+mod)%mod)%mod;//***相减一定要先加Mod再余Mod***
//for(j = l; j <= r; j++) {
//ans = (ans+(sum[j]-sum[l-1]+mod)%mod)%mod;
}
cout<<ans<<endl;
//cout << cnt << endl;
return 0;
}
本文深入探讨了如何使用二次前缀和算法解决区间求和问题,通过将原问题转化为求前缀和问题,有效提高了计算效率。文章详细介绍了算法的具体实现过程,包括两次求前缀和的步骤和关键代码,特别强调了在进行相减操作时应先加Mod再余Mod的重要性。
647

被折叠的 条评论
为什么被折叠?



