我需要编写一个程序,该程序可以有效地查找给定段(特定子数组)上最长的连续零序列的长度,[l, r]
并根据请求更新该值,这两个操作都以对数时间进行。
我有这个代码:
import java.io.*;
import java.util.Objects;
import java.util.StringTokenizer;
public class task {
static class treeLeaf {
int maxSeq;
int prefSeq;
int suffSeq;
int length;
treeLeaf(int maxSeq, int prefSeq, int suffSeq, int length) {
this.maxSeq = maxSeq;
this.prefSeq = prefSeq;
this.suffSeq = suffSeq;
this.length = length;
}
}
static treeLeaf merge(treeLeaf left, treeLeaf right) {
int maxSeq = Math.max(left.maxSeq, right.maxSeq);
if (left.suffSeq > 0 && right.prefSeq > 0) {
maxSeq = Math.max(maxSeq, left.suffSeq + right.prefSeq);
}
int prefSeq = left.prefSeq;
if (left.prefSeq == left.length) {
prefSeq += right.prefSeq;
}
int suffSeq = right.suffSeq;
if (right.suffSeq == right.length) {
suffSeq += left.suffSeq;
}
return new treeLeaf(maxSeq, prefSeq, suffSeq, left.length + right.length);
}
static treeLeaf rmq(int l, int r, treeLeaf[] tree) {
int n = tree.length / 2;
l += n;
r += n;
treeLeaf res = new treeLeaf(0, 0, 0, 0);
while (l <= r) {
if ((l & 1) == 1) {
res = merge(res, tree[l]);
l++;
}
if ((r & 1) == 0) {
res = merge(res, tree[r]);
r--;
}
if (l > r) break;
l /= 2;
r /= 2;
}
return res;
}
}
但是当我运行测试时:
18
6 0 0 1 0 0 0 0 2 4 5 6 9 0 0 0 0 1
1
QUERY 1 18
我的程序打印5
而不是4
. 我怀疑问题出在 function 上merge
,但我没有看到它......
您的
merge
方法不可交换,因此您不能以任意顺序合并。对于此版本的线段树,您可以将左侧的所有结果与右侧的结果分开合并,然后将这两个结果合并为循环后的最终答案。