import
java.util.Arrays;
public
class
Main {
static
final
int
N =
100000
;
static
int
[][] seg =
new
int
[N][
0
];
static
void
build(
int
ci,
int
st,
int
end,
int
[][] B)
{
if
(st == end) {
seg[ci] =
new
int
[] { B[st][
1
] };
return
;
}
int
mid = (st + end) /
2
;
build(
2
* ci +
1
, st, mid, B);
build(
2
* ci +
2
, mid +
1
, end, B);
seg[ci] = merge(seg[
2
* ci +
1
], seg[
2
* ci +
2
]);
}
static
int
[] merge(
int
[] a,
int
[] b)
{
int
i =
0
, j =
0
, k =
0
;
int
[] res =
new
int
[a.length + b.length];
while
(i < a.length && j < b.length) {
if
(a[i] < b[j]) {
res[k++] = a[i++];
}
else
{
res[k++] = b[j++];
}
}
while
(i < a.length) {
res[k++] = a[i++];
}
while
(j < b.length) {
res[k++] = b[j++];
}
return
res;
}
static
int
query(
int
ci,
int
st,
int
end,
int
l,
int
r,
int
k)
{
if
(st == end)
return
seg[ci][
0
];
int
p =
0
;
for
(
int
i =
0
; i < seg[
2
* ci +
1
].length; i++) {
if
(seg[
2
* ci +
1
][i] >= l
&& seg[
2
* ci +
1
][i] <= r) {
p++;
}
}
int
mid = (st + end) /
2
;
if
(p >= k)
return
query(
2
* ci +
1
, st, mid, l, r, k);
else
return
query(
2
* ci +
2
, mid +
1
, end, l, r,
k - p);
}
public
static
void
main(String[] args)
{
int
[] arr = {
3
,
1
,
5
,
2
,
4
,
7
,
8
,
6
};
int
n = arr.length;
int
[][] B =
new
int
[n][];
for
(
int
i =
0
; i < n; i++) {
B[i] =
new
int
[] { arr[i], i };
}
Arrays.sort(B,
(a, b) -> Integer.compare(a[
0
], b[
0
]));
build(
0
,
0
, n -
1
, B);
System.out.println(
"3rd smallest element in range 3 to 7 is: "
+ arr[query(
0
,
0
, n -
1
,
2
,
6
,
3
)]);
}
}