【acwing】前缀与差分

前缀和

题目

输入一个长度为 n的整数序列。

接下来再输入 m个询问,每个询问输入一对 l,r。

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式
第一行包含两个整数 n和 m。

第二行包含 n个整数,表示整数数列。

接下来 m行,每行包含两个整数 l和 r,表示一个询问的区间范围。

输出格式
共 m行,每行输出一个询问的结果。

求解

可以先用一个数组sum存储从0到i位置的前缀子列和。
sum[i] = sum[i-1]+a[i]
对于从第 l 个数到第 r 个数的和,可写作sum[r] - sum[l-1]

#include <iostream>

using namespace std;

int n, m;
int q[100010];
int sum[100010];

void addsum(int q[], int n){
    int i =0;
    sum[0] = 0;
    
    for(i =1; i<=n ;i++){
        sum[i] = sum[i-1] + q[i-1];
    }
}



int main(){
    cin>>n>>m;
    int i ;
    int start, end;
    for(i =0 ;i<n;i++){
        cin>>q[i];
    }
    addsum(q, n);
    for( i =0; i<m; i++){
        cin>>start>>end;
        cout<<sum[end] - sum[start-1]<<endl;
    }
    
    return 0;
    
    
}

子矩阵的和

输入一个 n行 m列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。

对于每个询问输出子矩阵中所有数的和。

输入格式
第一行包含三个整数 n,m,q。

接下来 n行,每行包含 m个整数,表示整数矩阵。

接下来 q行,每行包含四个整数 x1,y1,x2,y2,表示一组询问。

输出格式
共 q行,每行输出一个询问的结果。

思路
在这里插入图片描述

#include <iostream>

using namespace std;

int n, m;
int q[1001][1001];
int qu;
int s[1001][1001];

int main(){
    cin>>n>>m;
    cin>>qu;
    int i,j;
    for(i =0 ; i< n;i++){
        for(j =0 ; j< m; j++){
            cin>>q[i][j];
        }
    }
    
    s[1][1] = q[0][0];
    for(i =1 ; i<= n;i++){
        for(j =1 ; j<= m; j++){
            s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + q[i-1][j-1];
            //cout<<s[i][j]<<endl;
        }
    }
    
    int x1,y1,x2,y2;
    for( i =0 ; i<qu ;i++){
        cin>>x1>>y1>>x2>>y2;
        //cout<<s[x2][y2]<<" "<< s[x1-1][y2]<<" "<<s[x2][y1-1] <<" "<<s[x1-1][y1-1]<<endl;
        cout<<s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1]<<endl;
    }
    
    
    
    
    
    
}

差分

输入一个长度为 n的整数序列。

接下来输入 m个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r]之间的每个数加上 c。

请你输出进行完所有操作后的序列。

输入格式
第一行包含两个整数 n和 m。

第二行包含 n个整数,表示整数序列。

接下来 m行,每行包含三个整数 l,r,c,表示一个操作。

输出格式
共一行,包含 n个整数,表示最终序列。

思路
对原数组a构造差分数组b
在这里插入图片描述
试想 对从位置l开始到r的数组统统加c,直接循环需要(r-l+1)次
如果我们对其差分数组进行操作
b[l]+c后, 其原数组从i开始往后的所有数组都+c
b[r+1]+c后, 其原数组从r+1开始往后的所有数组都-c
所以。我们可以直接转换为
b[l]+= c;
b[r+1]-=c;

#include <iostream>

using namespace std;

int n;
int m;
int q[100001];
int b[100001];

int main(){
    cin>>n>>m;
    int i ;
    for(i=1; i<=n; i++){
        cin>>q[i];
    }
    
    for(i=1; i<=n ;i ++){
        b[i] = q[i] - q[i-1];
    }
    
    int l, r,c;
    for(i =0; i<m ;i++){
        cin>>l>>r>>c;
        b[l]+= c;
        b[r+1]-=c;
    }
    
    for(i=1; i<=n; i++){
        q[i] = q[i-1] + b[i];
        cout<<q[i]<<" ";
    }
    
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值