分苹果
时间限制: 1s
类别: 一维数组->较难
问题描述
小朋友排成一排,老师给他们分苹果。
小朋友从左到右标号1..N。有M个老师,每次第i个老师会给第Li个到第Ri个,一共Ri-Li+1个小朋友每人发Ci个苹果。
最后老师想知道每个小朋友有多少苹果。
输入说明
第一行两个整数N、M,表示小朋友个数和老师个数。
接下来M行,每行三个整数Li、Ri、Ci,意义如题目表述。
N、M≤100 000,1≤Li≤Ri≤N,0≤Ci≤100。
输出说明
一行N个数,第i个数表示第i个小朋友手上的水果。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
vector<int>diff(n + 1, 0);
//动态数组初始化
vector<int>apples(n + 1, 0);
int a, b, c;
for (int i = 0; i < m; i++)
{
cin >> a >> b >> c;
if (c == 0)continue;
diff[a] += c;
if (b + 1 <= n)
{
diff[b + 1] -= c;
}
}
for (int i = 1; i <= n; i++)
{
apples[i] = apples[i - 1] + diff[i];
cout << apples[i] << ' ';
}
return 0;
}
哦吼吼 你是不是以为这题很简单 然后发现tle了
哈哈 其实是算法的问题
很明显 那个案例是很多数据的 所以算法很重要
接下来 我向大家 介绍一种 算法 (差分数组)
这种算法 应对的是 对于 一个数组的 一个区间 同时加或减去某个数
这道例题就很经典了
差分数组 什么意思呢
比如 5个同学
此时 apples 0 0 0 0 0 0 (这里多开了一个数)
diff(表示的是 当前位置的apples个数 - 前一个位置的apples 个数)
也是 0 0 0 0 0 0 (同样多开一个数)
哎 这时候 说了 把第一个同学 到第 3个都加一
我们来调整差分数组
根据上面的定义可知
此时 diff 0 0 0 0 0 0 变成 diff 0 1(第一个数-第0个) 0(第2个-第一个) 0 -1(第4个-第3个) 0
于是通过模拟 我们可以知道 需要 diff[a]+=c ,diff[b+1]-=c;滴滴 这里需要判断一下
因为d可能是第n个人 那么d+1越界了
所以当d+1<=n的时候 diff[d+1]-=c;
这种操作 你发现 时间复杂度 变成 O(m)
不是O(m*平均区间长度)
(仅指加减操作的位置
然后就是打印
上面diff的定义可知
apples[i] = diff[i]+apples[i-1];
这里就给出了为神马 我们要在前面多弄一个0 不然 i从 0开始 -1又溢出了
为了不溢出 就得把第一项单独来看 即diff[1] =apples[1];
后面再按照公式来打印
如果有哪里有疑问可以评论 共同进步!