问题描述:
任务A.减去量
您有一个数组 a 长度 n 。有m个查询 ( l i ,r i ),对于每个 查找数字总和子数组 [ l i ,r i ]
输入数据格式:
第一行包含两个整数 n 和 m(1⩽n,m⩽ 10 5 ) -数字和查询数。第二 该行包含 n 个整数 a 1 ,a 2 。 。 。 , a n (1⩽a i ⩽10 9 ) - 数组。以下m行中的每行包含两个整数 l i 和 r i (1 l i r r i n) -查询。
输出数据格式:
对于每个请求,请在一行中单独回答。
我的解决方案:
#include <stdio.h>
int main(void) {
long n = 0;
long m = 0;
long l = 0;
long r = 0;
register long t = 0; // temporary variable, that contains intermediate results
scanf("%ld%ld", &n, &m);
long a[n];
long tr[m]; // array, that contains results
for (register long i = 0; i < n; i++)
scanf("%ld", &a[i]);
for (register long i = 0; i < m; i++) {
scanf("%ld%ld", &l, &r);
l--;
r--;
t = 0;
if (l != r) {
for (register long j = l; j <= r; j++)
t += *(a + j);
} else t = *(a + l);
tr[i] = t;
}
for (register long i = 0; i < m; i++)
printf("%ld\n", tr[i]);
return 0;
}
我的解决方案仅通过了11个中的6个测试。其他5个始终返回
时间超出错误
我真的是竞争编程的新手。 我应该如何优化代码以使big-O复杂度小于O(n 2 )? 任何帮助将不胜感激。 >
答案 0 :(得分:0)
计算数组的累加和并将其存储在另一个数组中,也就是说,
accumulated[i]
=直到第i个索引的数组数的总和。可以用O(n)来计算。
然后进行查询,答案将为accumulated[r] - accumulated[l]
。这是O(1)
答案 1 :(得分:0)
您可以使用前缀和方法来降低复杂度。假设一个长度为 4 的数组包含元素 a0、a1、a2、a3,创建一个单独的数组,其中包含索引 i 的 i 个元素的总和。
原始数组arr[]: a0, a1, a2, a3
前缀和数组 p[]: a0, a0+a1, a0+a1+a2, a0+a1+a2+a3
对于'a1和a2'的和:a1+a2 = p[2] - p[0]
对于'a1和a2和a3'的和:a1+a2+a3 = p[3] - p[0]
对于'a2和a3'的和:a2+a3 = p[3] - p[1]
以上几行表示对于从'L到R'的元素之和,我们必须打印p[R] - p[L-1]
注意:对于 L=0,我们必须打印 p[R],因为它是直到 R 的所有元素的总和,而且没有索引为 '-1' 的元素。
如果我们有一个包含 'long int' 数据类型并命名为 arr、大小为 n 的数组,则:
long p[n];
p[0] = arr[0];
for(long i=1;i<n;i++)
{
p[i] = p[i-1] + arr[i];
}