Arrays 应用相邻换位时,在次线性时间更新数组中的最大和次区间

Arrays 应用相邻换位时,在次线性时间更新数组中的最大和次区间,arrays,algorithm,dynamic-programming,amortized-analysis,Arrays,Algorithm,Dynamic Programming,Amortized Analysis,我问了一个关于一般换位的问题,这似乎太难了,我只得到了一个答案,这个答案似乎不能保证渐近加速。假设我们对一个数字数组应用一系列相邻的换位(一个相邻的换位交换两个相邻的数字),我们希望在每个相邻的换位之后保持最大和子区间的解。我们可以在每个相邻的换位之后,从头开始在整个阵列上重复Kadane的线性时间解。这就是我想要打败的。这可以在每个相邻换位的次线性时间内完成吗?比如说,如果我们对大小为N的数组进行N或N^2个相邻换位,并且允许我们对整个应用换位集合进行预处理,只要摊销的预处理时间是次线性的?这

我问了一个关于一般换位的问题,这似乎太难了,我只得到了一个答案,这个答案似乎不能保证渐近加速。假设我们对一个数字数组应用一系列相邻的换位(一个相邻的换位交换两个相邻的数字),我们希望在每个相邻的换位之后保持最大和子区间的解。我们可以在每个相邻的换位之后,从头开始在整个阵列上重复Kadane的线性时间解。这就是我想要打败的。这可以在每个相邻换位的次线性时间内完成吗?比如说,如果我们对大小为N的数组进行N或N^2个相邻换位,并且允许我们对整个应用换位集合进行预处理,只要摊销的预处理时间是次线性的?

这个答案描述了一个“双端”Kadane的变体,可作为O(logn)时间更新算法的基础。这种变体对于并行化也很有用

回想一下,Kadane的算法维护两个量:
max
(又称max\u so\u far)、最大子数组和和
max\u right
(又称max\u ending\u here),从右边界延伸的子数组的最大和。双端Kadane计算另外两个量:
max_left
,即从左边界延伸的子数组的最大和;
max_left_right
,即从左边界和右边界延伸的子数组的最大和(即数组的和)。将此信息存储在以下结构中

struct KadaneResult {
    int max;
    int max_right;
    int max_left;
    int max_left_right;
};
现在给定两个数组的结果结构,我们可以为它们的串联计算一个结果结构。如果您理解Kadane,并且我没有搞砸,那么正确性证明应该很容易:)

为了完整性,计算零和一个元素的结果结构

KadaneResult Zero() {
    KadaneResult zero;
    zero.max = 0;
    zero.max_right = 0;
    zero.max_left = 0;
    zero.max_left_right = 0;
    return zero;
}

KadaneResult One(int x) {
    KadaneResult one;
    one.max = maximum(0, x);
    one.max_right = maximum(0, x);
    one.max_left = maximum(0, x);
    one.max_left_right = x;
    return x;
}
现在,将所有这些结果结构放在一个列表中。每当您更新某个叶上的某个值时,请重新计算其祖先的结果结构,并读取根上的
max
字段。作为一种实用的优化,如果您检测到其中一次重新计算没有效果,您可以跳过后续更新。

此答案描述了Kadane的“双端”变体,可作为O(对数n)时间更新算法的基础。这种变体对于并行化也很有用

回想一下,Kadane的算法维护两个量:
max
(又称max\u so\u far)、最大子数组和和
max\u right
(又称max\u ending\u here),从右边界延伸的子数组的最大和。双端Kadane计算另外两个量:
max_left
,即从左边界延伸的子数组的最大和;
max_left_right
,即从左边界和右边界延伸的子数组的最大和(即数组的和)。将此信息存储在以下结构中

struct KadaneResult {
    int max;
    int max_right;
    int max_left;
    int max_left_right;
};
现在给定两个数组的结果结构,我们可以为它们的串联计算一个结果结构。如果您理解Kadane,并且我没有搞砸,那么正确性证明应该很容易:)

为了完整性,计算零和一个元素的结果结构

KadaneResult Zero() {
    KadaneResult zero;
    zero.max = 0;
    zero.max_right = 0;
    zero.max_left = 0;
    zero.max_left_right = 0;
    return zero;
}

KadaneResult One(int x) {
    KadaneResult one;
    one.max = maximum(0, x);
    one.max_right = maximum(0, x);
    one.max_left = maximum(0, x);
    one.max_left_right = x;
    return x;
}
现在,将所有这些结果结构放在一个列表中。每当您更新某个叶上的某个值时,请重新计算其祖先的结果结构,并读取根上的
max
字段。作为一种实用的优化,如果您检测到其中一次重新计算没有效果,您可以跳过后续更新。

此答案描述了Kadane的“双端”变体,可作为O(对数n)时间更新算法的基础。这种变体对于并行化也很有用

回想一下,Kadane的算法维护两个量:
max
(又称max\u so\u far)、最大子数组和和
max\u right
(又称max\u ending\u here),从右边界延伸的子数组的最大和。双端Kadane计算另外两个量:
max_left
,即从左边界延伸的子数组的最大和;
max_left_right
,即从左边界和右边界延伸的子数组的最大和(即数组的和)。将此信息存储在以下结构中

struct KadaneResult {
    int max;
    int max_right;
    int max_left;
    int max_left_right;
};
现在给定两个数组的结果结构,我们可以为它们的串联计算一个结果结构。如果您理解Kadane,并且我没有搞砸,那么正确性证明应该很容易:)

为了完整性,计算零和一个元素的结果结构

KadaneResult Zero() {
    KadaneResult zero;
    zero.max = 0;
    zero.max_right = 0;
    zero.max_left = 0;
    zero.max_left_right = 0;
    return zero;
}

KadaneResult One(int x) {
    KadaneResult one;
    one.max = maximum(0, x);
    one.max_right = maximum(0, x);
    one.max_left = maximum(0, x);
    one.max_left_right = x;
    return x;
}
现在,将所有这些结果结构放在一个列表中。每当您更新某个叶上的某个值时,请重新计算其祖先的结果结构,并读取根上的
max
字段。作为一种实用的优化,如果您检测到其中一次重新计算没有效果,您可以跳过后续更新。

此答案描述了Kadane的“双端”变体,可作为O(对数n)时间更新算法的基础。这种变体对于并行化也很有用

回想一下,Kadane的算法维护两个量:
max
(又称max\u so\u far)、最大子数组和和
max\u right
(又称max\u ending\u here),从右边界延伸的子数组的最大和。双端Kadane计算另外两个量:
max_left
,即从左边界延伸的子数组的最大和;
max_left_right
,即从左边界和右边界延伸的子数组的最大和(即数组的和)。将此信息存储在以下结构中

struct KadaneResult {
    int max;
    int max_right;
    int max_left;
    int max_left_right;
};
现在给出结果结构