Algorithm 如何以最佳时间复杂度高效地解决此问题?
在一个数组中给定一组N个数。给定Q查询。每个查询包含1个数字x 对于每个查询,需要向数组的每个元素添加x,然后报告数组中绝对值的总和 注意:对数组的更改是永久性的。有关更多说明,请参见示例 输入格式 第一行包含N,数组中的元素数。 下一行包含数组的N个空格分隔整数。 下一行包含Q(查询数)。 下一行包含Q空间分隔的整数(数字x) 输出格式 对于每个查询,以换行形式输出总和 约束条件Algorithm 如何以最佳时间复杂度高效地解决此问题?,algorithm,performance,logic,Algorithm,Performance,Logic,在一个数组中给定一组N个数。给定Q查询。每个查询包含1个数字x 对于每个查询,需要向数组的每个元素添加x,然后报告数组中绝对值的总和 注意:对数组的更改是永久性的。有关更多说明,请参见示例 输入格式 第一行包含N,数组中的元素数。 下一行包含数组的N个空格分隔整数。 下一行包含Q(查询数)。 下一行包含Q空间分隔的整数(数字x) 输出格式 对于每个查询,以换行形式输出总和 约束条件 1.≤ N≤ 500000 1.≤ Q≤ 500000 -2000 ≤ 每个查询中的数字≤ 2000年 -2000
1.≤ N≤ 500000
1.≤ Q≤ 500000
-2000 ≤ 每个查询中的数字≤ 2000年
-2000 ≤ 数组元素的值≤ 2000年 样本输入
3
-1 2 -3
3-1 2-3
3
1-2 3 样本输出
5
7
6
57
六, 解释 在查询1之后:[0,3,-2]=>sum=0+3+2=5 查询2之后:[-2,1,-4]=>sum=2+1+4=7 在查询3之后:[1,4,-1]=>sum=1+4+1=6
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,*a,q,*aq;
long int sum=0;
scanf("%d",&n);
a=(int*)malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("%d",&q);
aq=(int*)malloc(sizeof(int)*q);
for(int i=0;i<n;i++)
scanf("%d",&aq[i]);
for(int i=0;i<q;i++)
{
for(int j=0;j<n;j++)
{
sum+=abs(aq[i]+a[j]);
a[j]=aq[i]+a[j];
}
printf("%ld\n",sum);
sum=0;
}
}
#包括
#包括
int main()
{
整数n,*a,q,*aq;
长整数和=0;
scanf(“%d”和“&n”);
a=(int*)malloc(sizeof(int)*n);
对于(inti=0;i,您的解决方案正在执行N.Q操作,这是非常巨大的
首先请注意,数据的范围是适中的,因此您可以使用4001个条目的直方图来表示N个数字。该直方图在N次操作中计算(加上初始化存储箱)
然后将请求的总和作为每个bin的绝对差值之和,通过bin值进行加权。这将工作负载从N.Q降低到B.Q(B是bin的数量)
如果我是对的,我们可以通过将总和分解为负值和正值来做得更好。这些总和是通过计算前缀和得到的。这将导致在对B操作中的直方图进行预处理后,在Q操作中得到一个解决方案。以下是一个算法的概要:
样本输入
3
-1 2 -3
对数据进行排序并计算前缀和:
-3, -1, 2
-3, -4, -2 (prefix sums)
(使用直方图作为Yves Daoust将消除初始排序和任何二进制搜索以查找以下三个部分,这将显著优化复杂性。)
保持运行增量:
delta = 0
对于每个查询
1 -2 3
查询1:
* update delta:
delta = 0 + 1 = 1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * 1 + (-4 - 0)) + abs(1 * 1 + (-2 -(-4)))
= abs(2 - 4) + abs(1 + 2)
= 5
* update delta:
delta = 1 - 2 = -1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * (-1) + (-4 - 0)) + abs(1 * (-1) + (-2 -(-4)))
= abs(-2 - 4) + abs(-1 + 2)
= 7
* update delta:
delta = -1 + 3 = 2
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(1 * 2 + (-3 - 0)) + abs(1 * 2 + (-4 - (-3))) + abs(1 * 2 + (-2 -(-4)))
= abs(2 - 3) + abs(2 - 1) + abs(2 + 2)
= 6
查询-2:
* update delta:
delta = 0 + 1 = 1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * 1 + (-4 - 0)) + abs(1 * 1 + (-2 -(-4)))
= abs(2 - 4) + abs(1 + 2)
= 5
* update delta:
delta = 1 - 2 = -1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * (-1) + (-4 - 0)) + abs(1 * (-1) + (-2 -(-4)))
= abs(-2 - 4) + abs(-1 + 2)
= 7
* update delta:
delta = -1 + 3 = 2
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(1 * 2 + (-3 - 0)) + abs(1 * 2 + (-4 - (-3))) + abs(1 * 2 + (-2 -(-4)))
= abs(2 - 3) + abs(2 - 1) + abs(2 + 2)
= 6
查询3:
* update delta:
delta = 0 + 1 = 1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * 1 + (-4 - 0)) + abs(1 * 1 + (-2 -(-4)))
= abs(2 - 4) + abs(1 + 2)
= 5
* update delta:
delta = 1 - 2 = -1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * (-1) + (-4 - 0)) + abs(1 * (-1) + (-2 -(-4)))
= abs(-2 - 4) + abs(-1 + 2)
= 7
* update delta:
delta = -1 + 3 = 2
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(1 * 2 + (-3 - 0)) + abs(1 * 2 + (-4 - (-3))) + abs(1 * 2 + (-2 -(-4)))
= abs(2 - 3) + abs(2 - 1) + abs(2 + 2)
= 6
样本输出
5
7
6
对于每个查询,数组中的数字可能分别为负数、换号和正数。如果您不遵循Yves Daoust(狡猾)的建议对输入值进行bin(排序,在该词的一种解释中)排序,请考虑对它们进行排序(排序的另一种含义)。保留一个值偏移量以供每个查询修改(不更新数组项)和第一个非负项的索引。对于每个查询,后者将是“感兴趣的项”范围的一端-搜索另一端的-x
(由偏移量修改)。