码迷,mamicode.com
首页 > 其他好文 > 详细

前缀和、二维前缀和与差分

时间:2019-08-14 14:15:55      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:就是   ace   类型   return   include   ons   max   else   code   

前缀和

假如给出一串长度为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;
}

前缀和、二维前缀和与差分

标签:就是   ace   类型   return   include   ons   max   else   code   

原文地址:https://www.cnblogs.com/Emcikem/p/11351353.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!