给出数组中的一组N个数字。给定Q查询。每个查询包含1个数字x。
对于每个查询,您需要将x添加到数组的每个元素,然后报告数组中的绝对值之和。
注意:对数组的更改是永久的。请参阅示例以获取更多说明。
输入格式
第一行包含N,即数组中元素的数量。 下一行包含N个以空格分隔的整数数组。 下一行包含Q(查询数量)。 下一行包含Q个空格分隔的整数(数字x)。
输出格式
对于每个查询,在换行符中输出总和。
约束
1≤N≤500000
1≤Q≤500000
-2000≤每个查询中的数字≤2000
-2000≤数组元素的值≤2000
样本输入
3
-1 2 -3
3
1 -2 3
样本输出
5
7
6
说明
查询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;
}
}
一些测试用例正在超时。
答案 0 :(得分:2)
您的解决方案正在执行大量的N.Q操作。
首先请注意,数据范围适中,因此您可以使用4001个条目的直方图表示N个数字。此直方图是通过N次操作(加上初始化bin)计算出来的。
然后,将获得的请求总和作为每个bin的绝对差之和,并用bin值加权。这样可以将工作量从N.Q减少到B.Q(B是箱数)。
如果我是对的,我们可以通过分解一个负值和一个正值的总和来做得更好。并且这些和是通过计算前缀和而获得的。在对B运算中的直方图进行预处理之后,这应该会导致Q运算中的解决方案。
答案 1 :(得分:0)
以下是算法的概述:
样本输入
3
-1 2 -3
对数据进行排序并计算前缀总和:
-3, -1, 2
-3, -4, -2 (prefix sums)
(使用直方图作为Yves Daoust suggested可以消除初始排序和任何二进制搜索,从而找到下面的三个部分,这将极大地优化复杂性。)
维护运行中的增量:
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
查询-2:
* 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
查询3:
* 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