function
Segment() {
this
.leftToRight = [];
this
.rightToLeft = [];
}
Segment.prototype.addToLR =
function
(value) {
if
(
this
.leftToRight.length === 0) {
this
.leftToRight.push(value);
}
else
{
let lastElement =
this
.leftToRight[
this
.leftToRight.length - 1];
if
((lastElement & value) < lastElement) {
this
.leftToRight.push(lastElement & value);
}
}
};
Segment.prototype.addToRL =
function
(value) {
if
(
this
.rightToLeft.length === 0) {
this
.rightToLeft.push(value);
}
else
{
let lastElement =
this
.rightToLeft[
this
.rightToLeft.length - 1];
if
((lastElement & value) < lastElement) {
this
.rightToLeft.push(lastElement & value);
}
}
};
Segment.prototype.copyLR =
function
(lr) {
this
.leftToRight = lr.slice();
};
Segment.prototype.copyRL =
function
(rl) {
this
.rightToLeft = rl.slice();
};
function
divideThenConquer(ar, l, r, allPossibleAND) {
if
(l === r) {
allPossibleAND.add(ar[l]);
let ret =
new
Segment();
ret.leftToRight.push(ar[l]);
ret.rightToLeft.push(ar[l]);
return
ret;
}
else
{
let left = divideThenConquer(ar, l, Math.floor((l+r)/2), allPossibleAND);
let right = divideThenConquer(ar, Math.floor((l+r)/2)+1, r, allPossibleAND);
for
(let itr1 of left.rightToLeft) {
for
(let itr2 of right.leftToRight) {
allPossibleAND.add(itr1 & itr2);
}
}
return
mergeSegments(left, right);
}
}
function
mergeSegments(a, b) {
let res =
new
Segment();
res.copyLR(a.leftToRight);
res.copyRL(b.rightToLeft);
for
(let value of b.leftToRight) {
res.addToLR(value);
}
for
(let value of a.rightToLeft) {
res.addToRL(value);
}
return
res;
}
function
main() {
let ar = [11, 15, 7, 19];
let n = ar.length;
let allPossibleAND =
new
Set();
divideThenConquer(ar, 0, n-1, allPossibleAND);
console.log(allPossibleAND);
}
main();