for(i=0;i<k;i++)
{
l=sc.nextLong();
r=sc.nextLong();
v=sc.nextLong();
for(j=l-1;j<r;j++)
{
m=(int)j;
ar[m]=ar[m]+(long)v;
}
}
如何将其转换为单个for
循环?此代码导致我超时问题。代码的执行时间应低于2秒。这个是2秒。
答案 0 :(得分:1)
我认为你可以避免两个循环,但是你可以将它设为顺序,而不是嵌套。
long[] delta = new long[ar];
for(i=0;i<k;i++)
{
l=sc.nextLong();
r=sc.nextLong();
v=sc.nextLong();
if (l-1 < r) {
m=(int)(l-1);
delta[m] = v;
m=(int)r;
if (m < delta.length) {
delta[m] = -v;
}
}
}
long cumulative = 0;
for (int a = 0; a < ar.length; ++a) {
cumulative += delta[a];
ar[a] += cumulative;
}
不是为每个delta
范围继续增加l,r
中的值,而是仅存储一个&#34; delta&#34; array:这会在索引处存储+v
,您可以按v
开始递增数组;和-v
在您停止的索引处。因此,记录l
和r
之间的范围应增加v
现在是O(1)操作,而不是O(r-l)操作。
所以,这个数组的某些部分看起来像:
2
0 0 0 0 0 0 0 0 0 0
-2
(我只是垂直移动2s以使其更清晰)
如果计算这些元素的累计总和:
2 2 2 2 2 2
0 0 0 0 0 0
换句话说,您可以通过仅存储此范围的开始和结束位置来显示您将增加2的范围。
这是cumulative
变量存储的内容:它只是左边delta
数组中所有元素的总和,包括当前位置。这就是增加ar
的相应元素的数量。