Exemple #1
0
 public void Update(IncrementQueryObject updatedLeftChild, IncrementQueryObject updatedRightChild)
 {
     // Zero these out first as we want the total of the children's updated contributions.
     _remainder0CountWithoutRangeIncrements
           = _remainder1CountWithoutRangeIncrements
           = _remainder2CountWithoutRangeIncrements = 0;
     SubsumeRemainders(updatedLeftChild);
     SubsumeRemainders(updatedRightChild);
 }
Exemple #2
0
        public IncrementQueryObject Combine(IncrementQueryObject rightAdjacentObject)
        {
            var combinedQueryObject = new IncrementQueryObject();

            combinedQueryObject.SubsumeRemainders(this);
            combinedQueryObject.SubsumeRemainders(rightAdjacentObject);

            return(combinedQueryObject);
        }
Exemple #3
0
    // Instead of returning the children object directly, we have to add on the parent's range addition. The
    // children query object knows the subset of the parent segment it intersects with, and everything in
    // there needs the additions that were applied to the parent segment as a whole. It's kind of weird, any
    // pending range additions specifically for the children object gets brought out and added to the sum when
    // we do .Combine or .Sum, but recursively it makes sense: the children object has a sum but still needs
    // to know about the parent's range additions.
    public IncrementQueryObject Query(
        int treeArrayIndex, int segmentStartIndex, int segmentEndIndex,
        int queryStartIndex, int queryEndIndex)
    {
        var parentQueryObject = _treeArray[treeArrayIndex];

        if (queryStartIndex <= segmentStartIndex && queryEndIndex >= segmentEndIndex)
        {
            return(parentQueryObject);
        }

        int leftChildTreeArrayIndex  = (treeArrayIndex << 1) | 1;
        int rightChildTreeArrayIndex = leftChildTreeArrayIndex + 1;
        int leftChildSegmentEndIndex = (segmentStartIndex + segmentEndIndex) >> 1;
        IncrementQueryObject childrenQueryObject;

        if (queryStartIndex <= leftChildSegmentEndIndex && queryEndIndex > leftChildSegmentEndIndex)
        {
            childrenQueryObject = Query(
                leftChildTreeArrayIndex, segmentStartIndex, leftChildSegmentEndIndex,
                queryStartIndex, queryEndIndex)
                                  .Combine(Query(
                                               rightChildTreeArrayIndex, leftChildSegmentEndIndex + 1, segmentEndIndex,
                                               queryStartIndex, queryEndIndex));
        }
        else if (queryStartIndex <= leftChildSegmentEndIndex)
        {
            childrenQueryObject = Query(
                leftChildTreeArrayIndex, segmentStartIndex, leftChildSegmentEndIndex,
                queryStartIndex, queryEndIndex);
        }
        else
        {
            childrenQueryObject = Query(
                rightChildTreeArrayIndex, leftChildSegmentEndIndex + 1, segmentEndIndex,
                queryStartIndex, queryEndIndex);
        }

        var queryObject = new IncrementQueryObject
        {
            RangeIncrements = parentQueryObject.RangeIncrements
        };

        queryObject.SubsumeRemainders(childrenQueryObject);

        return(queryObject);
    }
Exemple #4
0
    private void Build(int treeArrayIndex, int segmentStartIndex, int segmentEndIndex)
    {
        if (segmentStartIndex == segmentEndIndex)
        {
            _treeArray[treeArrayIndex] = new IncrementQueryObject {
                Remainder0Count = 1
            };
            return;
        }

        int leftChildTreeArrayIndex  = (treeArrayIndex << 1) | 1;
        int rightChildTreeArrayIndex = leftChildTreeArrayIndex + 1;
        int leftChildSegmentEndIndex = (segmentStartIndex + segmentEndIndex) >> 1;

        Build(leftChildTreeArrayIndex, segmentStartIndex, leftChildSegmentEndIndex);
        Build(rightChildTreeArrayIndex, leftChildSegmentEndIndex + 1, segmentEndIndex);

        _treeArray[treeArrayIndex] = _treeArray[leftChildTreeArrayIndex].Combine(_treeArray[rightChildTreeArrayIndex]);
    }
Exemple #5
0
        public void SubsumeRemainders(IncrementQueryObject child)
        {
            switch (child.RangeIncrements % 3)
            {
            case 0:
                _remainder0CountWithoutRangeIncrements += child._remainder0CountWithoutRangeIncrements;
                _remainder1CountWithoutRangeIncrements += child._remainder1CountWithoutRangeIncrements;
                _remainder2CountWithoutRangeIncrements += child._remainder2CountWithoutRangeIncrements;
                break;

            case 1:
                _remainder0CountWithoutRangeIncrements += child._remainder2CountWithoutRangeIncrements;
                _remainder1CountWithoutRangeIncrements += child._remainder0CountWithoutRangeIncrements;
                _remainder2CountWithoutRangeIncrements += child._remainder1CountWithoutRangeIncrements;
                break;

            case 2:
                _remainder0CountWithoutRangeIncrements += child._remainder1CountWithoutRangeIncrements;
                _remainder1CountWithoutRangeIncrements += child._remainder2CountWithoutRangeIncrements;
                _remainder2CountWithoutRangeIncrements += child._remainder0CountWithoutRangeIncrements;
                break;
            }
        }