题目链接: oj
一维前缀和与一维差分算法
一维差分数组
一维差分数组可以在
O
(
1
)
O(1)
O(1)复杂度内,对数组一定范围内的数据进行值的统一加减;在
O
(
n
)
O(n)
O(n)复杂度内,查询数组元素的值。
题目模板大概是给一个大小为n的数组,然后进行m次操作,每次操作涉及多个数组元素。
一维前缀和
一维前缀和数组可以在
O
(
n
+
m
)
O(n+m)
O(n+m)复杂度内,求区间的和。
题目模板大概是给一个大小为n的数组,然后进行m次求和,每次操作涉及多个数组元素。暴力解法时间复杂度为
O
(
n
∗
m
)
O(n*m)
O(n∗m)。
70分解题思路
暴力解法就是每次问询,把整个数组遍历一遍判断是否合适。暴力解法时间复杂度为 O ( n ∗ m ) O(n*m) O(n∗m)。
70分代码
#include <stdio.h>
#include <vector>
using namespace std;
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
vector<int> t(n), c(n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &t[i], &c[i]);
}
for (int i = 0; i < m; i++)
{
int buf, left, right, count = 0;
scanf("%d", &buf);
for (int j = 0; j < n; j++)
{
left = buf + k;
right = buf + k + c[j] - 1;
if (t[j] <= right && t[j] >= left)
{
count++;
}
}
printf("%d\n", count);
}
return 0;
}
100分思路
暴力解法是从问询的角度出发,差分算法是从计划角度出发,即我计算好了每天做核酸所能完成的出行计划存起来,这样每次问询时我只需要查找数组就行了。时间复杂度为
O
(
n
)
O(n)
O(n)。
暴力解法中判断公式为
q
+
k
<
=
t
<
=
q
+
k
+
c
−
1
q+k<=t<=q+k+c-1
q+k<=t<=q+k+c−1
可以推出
q
<
=
t
−
k
q<=t-k
q<=t−k&&
q
>
=
t
−
k
−
c
+
1
q>=t-k-c+1
q>=t−k−c+1
所以对于每一个计划,我们把以上范围内所有元素都+1,最终就可以得到每天做核酸所能完成的所有出行计划。
AC代码
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 2e5+10;
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
int cnt[N] = {0};
for (int i = 0; i < n; i++)
{
int t, c, left, right;
scanf("%d%d", &t, &c);
left = t - k - c + 1;
right = t - k;
if (right <= 0)
continue;
left = max(1, left);
cnt[left]++;
//*****right+1
cnt[right+1]--;
}
int ans[N];
ans[0] = 0;
for (int i = 1; i < N; i++)
{
ans[i] = cnt[i] + ans[i - 1];
}
for (int i = 0; i < m; i++)
{
int q;
scanf("%d", &q);
printf("%d\n",ans[q]);
}
return 0;
}