蓝桥杯c++b组练习题自用记录6

差分与前缀和

模版(伪代码):

//读入原始数据 n,m,a

输入n,m

for(int i=0;i<n;i++){
    cin>>a[i]//输入原始数组 

//差分
for(int i=0;i<n;i++){
    b[i]=a[i]-a[i-1];
}  
//区间操作
while(m--){
    输入l,r,value
    b[l]=b[l]+value;//b代表了差 
    b[r+1]=b[r+1]-value;//对[l,r]区间的差进行加减操作 
}  
//前缀和还原
for(int i=0;i<n;i++) {
    b[i]=b[i]+b[i-1]
}

例题:大学里的树木要打药

题目描述
教室外有 N棵树(树的编号从 0∼N−1),根据不同的位置和树种,学校要对其上不同的药。

因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。

对于树的药是成区间分布,比如 3∼5 号的树靠近下水道,所以他们要用驱蚊虫的药, 20∼26 号的树,他们排水不好,容易涝所以要给他们用点促进根系的药 ...诸如此类。

每种不同的药要花不同的钱。

现在已知共有 M 个这样的区间,并且给你每个区间花的钱,问最后这些树木要花多少药费。

输入描述
每组输入的第一行有两个整数 N和 M。N 代表马路的共计多少棵树,M 代表区间的数目,N 和 M 之间用一个空格隔开。

接下来的 M 行每行包含三个不同的整数,用一个空格隔开,分别表示一个区域的起始点 L 和终止点 R的坐标,以及花费。

1≤L≤R≤N≤106,1≤M≤105,保证花费总和不超过 int 范围。

输出描述
输出包括一行,这一行只包含一个整数,所有的花费。

输入输出样例
示例

输入

500 3
150 300 4
100 200 20
470 471 19

输出

2662              

#include<bits/stdc++.h>
using namespace std;

const int N=1e6;
int b[N];
int n,m;//n层 m个 
int main(){     
	cin>>n>>m;
	while(m--){
		int l,r,value; 
		cin>>l>>r>>value;
		b[l+1]=b[l+1]+value;  //原数组即为差分数组,直接操作即可 
		b[r+1+1]=b[r+1+1]-value;  //对于每个 [l,r] 区间的加减操作都转化为对端点 l,r+1 的操作。
	}
	for(int i=1;i<=n;i++){
		b[i]=b[i]+b[i-1]; //前缀和还原 
	}
	int sum=0;
	for(int i=1;i<=n;i++){
		sum+=b[i];   
	}
	cout<<sum<<endl;
}           

 前缀和一般解题过程(伪代码):

输入n和m

输入n个值,并计算前缀和
for(int i=1;i<=n;i++) 
    输入a[i]
    并计算sum[i]=sum[i-1]+a[i] 
    
输入m个区间,计算结果
while(m)
    m=m-1
    输入l,r
    计算sum[r]-sum[l-1]区间的和,并输出 

例题:大学里的树木要维护


题目描述
教室外有 N棵树(树的编号从 1∼N),根据不同的位置和树种,学校已经对其进行了多年的维护。

因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。

由于已经维护了多年,每一个树都由学校的园艺人员进行了维护费用的统计。

每棵树的前期维护费用各不相同,但是由于未来需要要打药,所以有些树木的维护费用太高的话,就要重新种植。

由于维护费用也称区间分布,所以常常需要统一个区间里的树木的维护开销。

现给定一个长度为 N的数组 A以及 M个查询,Ai​ 表示第 ii 棵树到维护费用。对于每个查询包含一个区间,园艺人员想知道该区间内的树木维护的开销是多少。

请你编写程序帮帮他!

输入描述
每组输入的第一行有两个整数 N和 M。N 代表马路的共计多少棵树,M代表区间的数目,N和 M 之间用一个空格隔开。

接下来的一行,包含 N 个数 A1​,A2​,⋯,AN​,分别表示每棵树的维护费用,每个数之间用空格隔开。

接下来的 M 行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点 L和终止点 R 的坐标。

输出描述
输出包括 M行,每一行只包含一个整数,表示维护的开销。

输入输出样例
示例

输入

10 3
7 5 6 4 2 5 0 8 5 3
1 5
2 6
3 7


输出

24
22
17

#include<bits/stdc++.h> // 包含标准 C++ 库的所有头文件
using namespace std;

int a[100005]; // 数字数组
int sum[100005]; // 前缀和数组
vector<int> ss; // 结果数组

int main() {
    int n; // 数字三角形的行数
    int m; // 查询次数

    cin >> n >> m; // 输入数字三角形的行数和查询次数

    // 读取数字三角形的每一行,同时计算每行数字的前缀和
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum[i] = a[i] + sum[i - 1];
    }

    // 处理查询操作
    while (m > 0) {
        m--; // 每处理一个查询,m 减一
        int l, r;
        cin >> l >> r; // 输入查询区间的左右边界
        // 计算查询区间的和,并将结果存入结果数组
        ss.push_back(sum[r] - sum[l - 1]);
    }

    // 输出结果数组中的每一个元素
    for (auto sss : ss)
        cout << sss << endl; // 输出当前元素并换行

    return 0; // 返回 0,表示程序正常结束
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值