Preciso escrever um programa que encontre com eficiência o comprimento da maior sequência contínua de zeros em um determinado segmento [l, r]
(uma submatriz específica) e atualize o valor, se solicitado, ambas as operações em tempo logarítmico.
Eu tenho este código:
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;
}
}
Mas quando executo o teste:
18
6 0 0 1 0 0 0 0 2 4 5 6 9 0 0 0 0 1
1
QUERY 1 18
Meu programa imprime 5
em vez de 4
. Suspeito que o problema seja com function merge
, mas não vejo isso ...
Seu
merge
método não é comutativo, portanto você não pode mesclar em ordem arbitrária. Para esta versão da árvore de segmentos, você pode mesclar todos os resultados do lado esquerdo separadamente dos resultados do lado direito e, em seguida, mesclar esses dois resultados para a resposta final após o loop.