You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.8 KiB
180 lines
4.8 KiB
// 线段树 |
|
(function () { |
|
var parent = function (node) { |
|
return Math.floor(node / 2); |
|
}; |
|
|
|
var Int32Array = _global.Int32Array || function (size) { |
|
var xs = []; |
|
for (var i = size - 1; i >= 0; --i) { |
|
xs[i] = 0; |
|
} |
|
return xs; |
|
}; |
|
|
|
var ceilLog2 = function (x) { |
|
var y = 1; |
|
while (y < x) { |
|
y *= 2; |
|
} |
|
return y; |
|
}; |
|
|
|
BI.PrefixIntervalTree = function (xs) { |
|
this._size = xs.length; |
|
this._half = ceilLog2(this._size); |
|
// _heap是一个_size两倍以上的堆 |
|
this._heap = new Int32Array(2 * this._half); |
|
|
|
var i; |
|
// 初始化 >= _size 的堆空间, 即叶子节点 |
|
for (i = 0; i < this._size; ++i) { |
|
this._heap[this._half + i] = xs[i]; |
|
} |
|
// 初始化 < _size 的堆空间, 即非叶子节点,根节点包含整个区间 |
|
for (i = this._half - 1; i > 0; --i) { |
|
this._heap[i] = this._heap[2 * i] + this._heap[2 * i + 1]; |
|
} |
|
}; |
|
|
|
BI.PrefixIntervalTree.prototype = { |
|
constructor: BI.PrefixIntervalTree, |
|
// 往_half之后的空间set值,需要更新其所有祖先节点的值 |
|
set: function (index, value) { |
|
var node = this._half + index; |
|
this._heap[node] = value; |
|
|
|
node = parent(node); |
|
for (; node !== 0; node = parent(node)) { |
|
this._heap[node] = |
|
this._heap[2 * node] + this._heap[2 * node + 1]; |
|
} |
|
}, |
|
|
|
get: function (index) { |
|
var node = this._half + index; |
|
return this._heap[node]; |
|
}, |
|
|
|
getSize: function () { |
|
return this._size; |
|
}, |
|
|
|
/** |
|
* get(0) + get(1) + ... + get(end - 1). |
|
*/ |
|
sumUntil: function (end) { |
|
if (end === 0) { |
|
return 0; |
|
} |
|
|
|
var node = this._half + end - 1; |
|
var sum = this._heap[node]; |
|
for (; node !== 1; node = parent(node)) { |
|
if (node % 2 === 1) { |
|
sum += this._heap[node - 1]; |
|
} |
|
} |
|
|
|
return sum; |
|
}, |
|
|
|
/** |
|
* get(0) + get(1) + ... + get(inclusiveEnd). |
|
*/ |
|
sumTo: function (inclusiveEnd) { |
|
return this.sumUntil(inclusiveEnd + 1); |
|
}, |
|
|
|
/** |
|
* sum get(begin) + get(begin + 1) + ... + get(end - 1). |
|
*/ |
|
sum: function (begin, end) { |
|
return this.sumUntil(end) - this.sumUntil(begin); |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or |
|
* -1 if no such i exists. |
|
*/ |
|
greatestLowerBound: function (t) { |
|
if (t < 0) { |
|
return -1; |
|
} |
|
|
|
var node = 1; |
|
if (this._heap[node] <= t) { |
|
return this._size; |
|
} |
|
|
|
while (node < this._half) { |
|
var leftSum = this._heap[2 * node]; |
|
if (t < leftSum) { |
|
node = 2 * node; |
|
} else { |
|
node = 2 * node + 1; |
|
t -= leftSum; |
|
} |
|
} |
|
|
|
return node - this._half; |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or |
|
* -1 if no such i exists. |
|
*/ |
|
greatestStrictLowerBound: function (t) { |
|
if (t <= 0) { |
|
return -1; |
|
} |
|
|
|
var node = 1; |
|
if (this._heap[node] < t) { |
|
return this._size; |
|
} |
|
|
|
while (node < this._half) { |
|
var leftSum = this._heap[2 * node]; |
|
if (t <= leftSum) { |
|
node = 2 * node; |
|
} else { |
|
node = 2 * node + 1; |
|
t -= leftSum; |
|
} |
|
} |
|
|
|
return node - this._half; |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or |
|
* size + 1 if no such i exists. |
|
*/ |
|
leastUpperBound: function (t) { |
|
return this.greatestStrictLowerBound(t) + 1; |
|
}, |
|
|
|
/** |
|
* Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or |
|
* size + 1 if no such i exists. |
|
*/ |
|
leastStrictUpperBound: function (t) { |
|
return this.greatestLowerBound(t) + 1; |
|
} |
|
}; |
|
|
|
BI.PrefixIntervalTree.uniform = function (size, initialValue) { |
|
var xs = []; |
|
for (var i = size - 1; i >= 0; --i) { |
|
xs[i] = initialValue; |
|
} |
|
|
|
return new BI.PrefixIntervalTree(xs); |
|
}; |
|
|
|
BI.PrefixIntervalTree.empty = function (size) { |
|
return BI.PrefixIntervalTree.uniform(size, 0); |
|
}; |
|
|
|
})();
|
|
|