public
class
GFG {
public
int
removeMinElements(
int
[] a)
{
int
n = a.length;
RangeMinimumQuery rMimQ =
new
RangeMinimumQuery();
int
[] minTree = rMimQ.createSegmentTree(a);
RangeMaximumQuery rMaxQ =
new
RangeMaximumQuery();
int
[] maxTree = rMaxQ.createSegmentTree(a);
int
start =
0
, end =
0
;
int
min, max;
int
maxValidLen =
0
;
while
(end < n) {
min = rMimQ.rangeMinimumQuery(minTree,
start, end, n);
max = rMaxQ.rangeMaximumQuery(maxTree,
start, end, n);
if
(
2
* min <= max)
start++;
else
maxValidLen = Math.max(maxValidLen,
end - start +
1
);
end++;
}
return
n - maxValidLen;
}
class
RangeMinimumQuery {
public
int
[] createSegmentTree(
int
[] input)
{
int
n = input.length;
int
segTreeSize =
2
* getNextPowerOfTwo(n) -
1
;
int
[] segmentTree =
new
int
[segTreeSize];
createSegmentTreeUtil(segmentTree, input,
0
, n -
1
,
0
);
return
segmentTree;
}
private
void
createSegmentTreeUtil(
int
[] segmentTree,
int
[] input,
int
low,
int
high,
int
pos)
{
if
(low == high) {
segmentTree[pos] = input[low];
return
;
}
int
mid = (low + high) /
2
;
createSegmentTreeUtil(segmentTree, input, low,
mid, (
2
* pos +
1
));
createSegmentTreeUtil(segmentTree, input,
mid +
1
, high, (
2
* pos +
2
));
segmentTree[pos] = Math.min(segmentTree[
2
* pos +
1
],
segmentTree[
2
* pos +
2
]);
}
public
int
rangeMinimumQuery(
int
[] segmentTree,
int
from,
int
to,
int
inputSize)
{
return
rangeMinimumQueryUtil(segmentTree,
0
,
inputSize -
1
, from, to,
0
);
}
private
int
rangeMinimumQueryUtil(
int
[] segmentTree,
int
low,
int
high,
int
from,
int
to,
int
pos)
{
if
(from <= low && to >= high) {
return
segmentTree[pos];
}
if
(from > high || to < low) {
return
Integer.MAX_VALUE;
}
int
mid = (low + high) /
2
;
int
left = rangeMinimumQueryUtil(segmentTree, low,
mid, from, to,
(
2
* pos +
1
));
int
right = rangeMinimumQueryUtil(segmentTree,
mid +
1
, high, from,
to, (
2
* pos +
2
));
return
Math.min(left, right);
}
}
class
RangeMaximumQuery {
public
int
[] createSegmentTree(
int
[] input)
{
int
n = input.length;
int
segTreeSize =
2
* getNextPowerOfTwo(n) -
1
;
int
[] segmentTree =
new
int
[segTreeSize];
createSegmentTreeUtil(segmentTree, input,
0
, n -
1
,
0
);
return
segmentTree;
}
private
void
createSegmentTreeUtil(
int
[] segmentTree,
int
[] input,
int
low,
int
high,
int
pos)
{
if
(low == high) {
segmentTree[pos] = input[low];
return
;
}
int
mid = (low + high) /
2
;
createSegmentTreeUtil(segmentTree, input, low,
mid, (
2
* pos +
1
));
createSegmentTreeUtil(segmentTree, input,
mid +
1
, high, (
2
* pos +
2
));
segmentTree[pos] = Math.max(segmentTree[
2
* pos +
1
],
segmentTree[
2
* pos +
2
]);
}
public
int
rangeMaximumQuery(
int
[] segmentTree,
int
from,
int
to,
int
inputSize)
{
return
rangeMaximumQueryUtil(segmentTree,
0
,
inputSize -
1
, from, to,
0
);
}
private
int
rangeMaximumQueryUtil(
int
[] segmentTree,
int
low,
int
high,
int
from,
int
to,
int
pos)
{
if
(from <= low && to >= high) {
return
segmentTree[pos];
}
if
(from > high || to < low) {
return
Integer.MIN_VALUE;
}
int
mid = (low + high) /
2
;
int
left = rangeMaximumQueryUtil(segmentTree, low,
mid, from, to,
(
2
* pos +
1
));
int
right = rangeMaximumQueryUtil(segmentTree,
mid +
1
, high, from,
to, (
2
* pos +
2
));
return
Math.max(left, right);
}
}
private
int
getNextPowerOfTwo(
int
n)
{
int
logPart = (
int
)Math.ceil(Math.log(n)
/ Math.log(
2
));
return
(
int
)Math.pow(
2
, logPart);
}
public
static
void
main(String[] args)
{
int
[] a = {
4
,
5
,
100
,
9
,
10
,
11
,
12
,
15
,
200
};
GFG gfg =
new
GFG();
System.out.println(gfg.removeMinElements(a));
}
}