题目描述
教室外有 NN 棵树(树的编号从 0\sim N-10∼N−1),根据不同的位置和树种,学校要对其上不同的药。
因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。
对于树的药是成区间分布,比如 3 \sim 53∼5 号的树靠近下水道,所以他们要用驱蚊虫的药, 20 \sim 2620∼26 号的树,他们排水不好,容易涝所以要给他们用点促进根系的药 \cdots⋯诸如此类。
每种不同的药要花不同的钱。
现在已知共有 MM 个这样的区间,并且给你每个区间花的钱,问最后这些树木要花多少药费。
输入描述
每组输入的第一行有两个整数 NN和 MM。NN 代表马路的共计多少棵树,MM 代表区间的数目,NN 和 MM 之间用一个空格隔开。
接下来的 MM 行每行包含三个不同的整数,用一个空格隔开,分别表示一个区域的起始点 LL 和终止点 RR 的坐标,以及花费。
1\leq L\leq R \leq N \leq 10^6,1\leq M\leq 10^51≤L≤R≤N≤106,1≤M≤105,保证花费总和不超过 int
范围。
输出描述
输出包括一行,这一行只包含一个整数,所有的花费。
输入输出样例
示例
输入
500 3
150 300 4
100 200 20
470 471 19
输出
2662
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
思路
题目大意,假设一段路,500棵树,分3个区间,第一个区间每颗树都要4,第二个区间每棵树20,第三19。只要每个树赋上对应的值,用sum遍历整段路,累加起来就是ans,关键是如何给树加值。注意:区间是可能重复的,所以不能直接赋值要累加
能直接想到的就是,遍历3次:第一次即第一个区间从L到R,遍历R-L次,给第一区间每个树+4;第二次,第三次同理。完成所有树,共需要n次,时间复杂度为On
再遍历n次,把每个值累加到sum就是答案,也需要n次。
for (i = 0; i < m; i++) {
int L, R;
cin >> L >> R >> v;
for (int j = L; j <= R; j++)
b[j] += v;
}
int sum = 0;
for (i = 0; i < n; i++)
sum += b[i];
cout << sum;
第二种,用差分数组在b[L]+v,b[L]-v,然后变成前缀和数组,达到同样的效果,每个树有对应的值,最后累加同上。
for (i = 0; i < m; i++) {
int L, R;
cin >> L >> R >> v;
b[L]+=v;
b[R+1]-=v;
}
for(int i=0;i<n;i++){
b[i]+=b[i-1];
}
int sum = 0;
for (i = 0; i < n; i++)
sum += b[i];
cout << sum;
或者
for (i = 0; i < m; i++) {
int L, R;
cin >> L >> R >> v;
b[L+1]+=v;
b[R+1+1]-=v;
}
for(int i=1;i<=n;i++){
b[i]+=b[i-1];
}
int sum = 0;
for (i = 1; i <= n; i++)
sum += b[i];
cout << sum;
源代码
#include <iostream>
using namespace std;
int b[100005];
int main()
{
// 请在此输入您的代码
int n, m, i, v;
cin >> n >> m;
//输入区间
for (i = 0; i < m; i++) {
int L, R;
cin >> L >> R >> v;
b[L]+=v;
b[R+1]-=v;
}
//将b自身重新构建成前缀和数组
for(int i=0;i<n;i++){
b[i]+=b[i-1];
}
//计算答案
int sum = 0;
for (i = 0; i < n; i++)
sum += b[i];
cout << sum;
return 0;
}