前缀和
假如给出一串长度为n的数列a1,a2,a3...an,再给出m个询问,每次询问给出L,R两个数,要求给出数列在区间[L,R]的和
普通的方法,时间复杂度为O(n*m)
int a[100005];
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int sum=0;
while(m--){
for(int i=L;i<=R;i++){
sum+=a[i];
}
}
前缀和就是前面i个数的总和,对于每个询问,只需要输出a[R]-a[L-1]即可
用前缀和的方法,时间复杂度O(m+n)
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
}
差分
假如给出一串长度为n的数列a1,a2,a3...an,再给出m次以及不同的L和R[L,R]操作
操作一:将[L,R]内的元素都加上P
操作二:将[L,R]内的元素都减去P
最后求[L,R]内的元素之和
普通方法时间复杂度为O(m*n)
利用差分
#include <bits/stdc++.h>
using namespace std;
const int manx=1e5+5;
int a[maxn],b[maxn];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++){
int l,r,t,p;//t为操作类型,p为加减的大小
cin>>t>>l>>r>>p;
if(t==1){//t==1表示加
b[l]+=p;b[r+1]-=p;//因为操作一我只需对[L,R]区间里的数加p,[R+1,n]这个区间里的数没必要加p,所以需要减掉p。
}else{//t==0表示减
b[l]-=p;b[r+1]+=p;
}
}
int add=0;
for(int i=1;i<=n;i++){
sum+=b[i];
a[i]+=a[i-1]+add;
}
cin>>l>>r;
printf("%d\n",a[r]-a[l-1]);
return 0;
}
原文地址:https://www.cnblogs.com/Emcikem/p/11351353.html
时间: 2024-10-02 07:58:43