Skip to content

Commit

Permalink
Worked on issue #208
Browse files Browse the repository at this point in the history
  • Loading branch information
William Fiset authored and William Fiset committed Aug 4, 2020
1 parent d0058c5 commit 578e264
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,18 @@ private static class Segment {
Long value;
Long lazy;

// Use for Min/Max mul queries
Long min, max;

// The range of the segment [tl, tr]
int tl;
int tr;

public Segment(int i, Long value, int tl, int tr) {
public Segment(int i, Long value, Long min, Long max, int tl, int tr) {
this.i = i;
this.value = value;
this.min = min;
this.max = max;
this.tl = tl;
this.tr = tr;
}
Expand Down Expand Up @@ -117,8 +122,20 @@ private Long safeMax(Long a, Long b) {
private Ruf lminQuerySumUpdate = (s, x) -> safeSum(s.lazy, x);

// // TODO(issue/208): support this multiplication update
private Ruf minQueryMulUpdate = (s, x) -> safeMul(s.value, x);
private Ruf lminQueryMulUpdate = (s, x) -> safeMul(s.value, x); // s.lazy?
private Ruf minQueryMulUpdate =
(s, x) -> {
if (x < 0) {
// s.min was already calculated
if (safeMul(s.value, x) == s.min) {
return s.max;
} else {
return s.min;
}
} else {
return safeMul(s.value, x);
}
};
private Ruf lminQueryMulUpdate = (s, x) -> safeMul(s.lazy, x);

private Ruf minQueryAssignUpdate = (s, x) -> x;
private Ruf lminQueryAssignUpdate = (s, x) -> x;
Expand All @@ -127,8 +144,19 @@ private Long safeMax(Long a, Long b) {
private Ruf lmaxQuerySumUpdate = (s, x) -> safeSum(s.lazy, x);

// TODO(issue/208): support this multiplication update
private Ruf maxQueryMulUpdate = (s, x) -> safeMul(s.value, x);
private Ruf lmaxQueryMulUpdate = (s, x) -> safeMul(s.value, x); // s.lazy?
private Ruf maxQueryMulUpdate =
(s, x) -> {
if (x < 0) {
if (safeMul(s.value, x) == s.min) {
return s.max;
} else {
return s.min;
}
} else {
return safeMul(s.value, x);
}
};
private Ruf lmaxQueryMulUpdate = (s, x) -> safeMul(s.lazy, x);

private Ruf maxQueryAssignUpdate = (s, x) -> x;
private Ruf lmaxQueryAssignUpdate = (s, x) -> x;
Expand Down Expand Up @@ -221,15 +249,17 @@ public GenericSegmentTree2(
*/
private void buildSegmentTree(int i, int tl, int tr, long[] values) {
if (tl == tr) {
st[i] = new Segment(i, values[tl], tl, tr);
st[i] = new Segment(i, values[tl], values[tl], values[tl], tl, tr);
return;
}
int tm = (tl + tr) / 2;
buildSegmentTree(2 * i + 1, tl, tm, values);
buildSegmentTree(2 * i + 2, tm + 1, tr, values);

Long segmentValue = combinationFn.apply(st[2 * i + 1].value, st[2 * i + 2].value);
Segment segment = new Segment(i, segmentValue, tl, tr);
Long minValue = Math.min(st[2 * i + 1].min, st[2 * i + 2].min);
Long maxValue = Math.max(st[2 * i + 1].max, st[2 * i + 2].max);
Segment segment = new Segment(i, segmentValue, minValue, maxValue, tl, tr);

st[i] = segment;
}
Expand Down Expand Up @@ -274,6 +304,10 @@ private Long rangeQuery1(int i, int tl, int tr, int l, int r) {
// Apply the delta value to the current node and push it to the child segments
private void propagate1(int i, int tl, int tr) {
if (st[i].lazy != null) {
// Only used for min/max mul queries
st[i].min = st[i].min * st[i].lazy;
st[i].max = st[i].max * st[i].lazy;

// Apply the delta to the current segment.
st[i].value = ruf.apply(st[i], st[i].lazy);
// Push the delta to left/right segments for non-leaf nodes
Expand All @@ -300,6 +334,9 @@ private void rangeUpdate1(int i, int tl, int tr, int l, int r, long x) {
}

if (tl == l && tr == r) {
st[i].min = st[i].min * x;
st[i].max = st[i].max * x;

st[i].value = ruf.apply(st[i], x);
propagateLazy1(i, tl, tr, x);
} else {
Expand All @@ -311,6 +348,8 @@ private void rangeUpdate1(int i, int tl, int tr, int l, int r, long x) {
rangeUpdate1(2 * i + 2, tm + 1, tr, Math.max(l, tm + 1), r, x);

st[i].value = combinationFn.apply(st[2 * i + 1].value, st[2 * i + 2].value);
st[i].max = Math.max(st[2 * i + 1].max, st[2 * i + 2].max);
st[i].min = Math.min(st[2 * i + 1].min, st[2 * i + 2].min);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,20 +205,91 @@ public void maxQuerySumUpdate_simple() {
}

@Test
public void maxQueryMulUpdate_simple() {
public void maxminQueryMulUpdate_simple() {
long[] ar = {2, 1, 3, 4, -1};
GenericSegmentTree2 st =
GenericSegmentTree2 st1 =
new GenericSegmentTree2(
ar,
GenericSegmentTree2.SegmentCombinationFn.MAX,
GenericSegmentTree2.RangeUpdateFn.MULTIPLICATION);
GenericSegmentTree2 st2 =
new GenericSegmentTree2(
ar,
GenericSegmentTree2.SegmentCombinationFn.MIN,
GenericSegmentTree2.RangeUpdateFn.MULTIPLICATION);

st.rangeUpdate1(0, 4, 1);
assertThat(st.rangeQuery1(0, 4)).isEqualTo(4);
st1.rangeUpdate1(0, 4, 1);
st2.rangeUpdate1(0, 4, 1);

assertThat(st1.rangeQuery1(0, 4)).isEqualTo(4);
assertThat(st2.rangeQuery1(0, 4)).isEqualTo(-1);

// TODO(issue/208): Negative numbers are a known issue
// st.rangeUpdate1(0, 4, -2);
// assertThat(st.rangeQuery1(0, 4)).isEqualTo(2); // Returns -8 as max but should be 2
st1.rangeUpdate1(0, 4, -2);
st2.rangeUpdate1(0, 4, -2);

assertThat(st1.rangeQuery1(0, 4)).isEqualTo(2);
assertThat(st2.rangeQuery1(0, 4)).isEqualTo(-8);

st1.rangeUpdate1(0, 4, -1);
st2.rangeUpdate1(0, 4, -1);

assertThat(st1.rangeQuery1(0, 4)).isEqualTo(8);
assertThat(st2.rangeQuery1(0, 4)).isEqualTo(-2);
}

@Test
public void maxQueryMulUpdate_simple() {
long[] ar = {2, 1, 3, 4, -1};
GenericSegmentTree2 st1 =
new GenericSegmentTree2(
ar,
GenericSegmentTree2.SegmentCombinationFn.MAX,
GenericSegmentTree2.RangeUpdateFn.MULTIPLICATION);

// [4, 2, 6, 8, -2]
st1.rangeUpdate1(0, 4, 2);
assertThat(st1.rangeQuery1(0, 4)).isEqualTo(8);
assertThat(st1.rangeQuery1(0, 0)).isEqualTo(4);
assertThat(st1.rangeQuery1(0, 1)).isEqualTo(4);
assertThat(st1.rangeQuery1(0, 2)).isEqualTo(6);
assertThat(st1.rangeQuery1(1, 3)).isEqualTo(8);

// [4, 2, 6, -16, 4]
st1.rangeUpdate1(3, 4, -2);
assertThat(st1.rangeQuery1(0, 4)).isEqualTo(6);
assertThat(st1.rangeQuery1(0, 0)).isEqualTo(4);
assertThat(st1.rangeQuery1(0, 1)).isEqualTo(4);
assertThat(st1.rangeQuery1(0, 2)).isEqualTo(6);
assertThat(st1.rangeQuery1(1, 3)).isEqualTo(6);
assertThat(st1.rangeQuery1(3, 4)).isEqualTo(4);
}

@Test
public void minQueryMulUpdate_simple() {
long[] ar = {2, 1, 3, 4, -1};
GenericSegmentTree2 st1 =
new GenericSegmentTree2(
ar,
GenericSegmentTree2.SegmentCombinationFn.MIN,
GenericSegmentTree2.RangeUpdateFn.MULTIPLICATION);

// [4, 2, 6, 8, -2]
st1.rangeUpdate1(0, 4, 2);
assertThat(st1.rangeQuery1(0, 4)).isEqualTo(-2);
assertThat(st1.rangeQuery1(0, 0)).isEqualTo(4);
assertThat(st1.rangeQuery1(0, 1)).isEqualTo(2);
assertThat(st1.rangeQuery1(0, 2)).isEqualTo(2);
assertThat(st1.rangeQuery1(1, 3)).isEqualTo(2);

// [4, 2, 6, -16, 4]
st1.rangeUpdate1(3, 4, -2);
assertThat(st1.rangeQuery1(0, 4)).isEqualTo(-16);
assertThat(st1.rangeQuery1(0, 0)).isEqualTo(4);
assertThat(st1.rangeQuery1(0, 1)).isEqualTo(2);
assertThat(st1.rangeQuery1(0, 2)).isEqualTo(2);
assertThat(st1.rangeQuery1(1, 3)).isEqualTo(-16);
assertThat(st1.rangeQuery1(3, 4)).isEqualTo(-16);
}

@Test
Expand Down

0 comments on commit 578e264

Please sign in to comment.