import
java.util.*;
public
class
GFG {
static
List<List<Long> > tree
=
new
ArrayList<>();
public
static
void
main(String[] args)
{
List<Integer> arr = Arrays.asList(
12
,
8
,
11
,
13
,
10
,
15
,
14
,
16
,
20
);
int
k =
4
;
System.out.println(
"Number of Increasing Subsequences of size "
+ k
+
" = "
+ numOfIncSubseqOfSizeK(arr, k));
}
static
int
RANKER(List<Integer> arr)
{
int
n = arr.size();
List<Integer> temp =
new
ArrayList<>(arr);
temp.sort(Comparator.naturalOrder());
Map<Integer, Integer> mpp =
new
HashMap<>();
int
mx =
0
;
for
(
int
i =
0
; i < n; i++) {
if
(!mpp.containsKey(temp.get(i))) {
mpp.put(temp.get(i), mx);
mx++;
}
}
for
(
int
i =
0
; i < n; i++) {
arr.set(i, mpp.get(arr.get(i)));
}
return
mx;
}
static
List<Long> summation(List<Long> left,
List<Long> right,
int
k)
{
List<Long> res =
new
ArrayList<>(
Collections.nCopies(k +
1
, 0L));
for
(
int
i =
1
; i <= k; i++) {
res.set(i, left.get(i) + right.get(i));
}
return
res;
}
static
List<Long> query(
int
start,
int
end,
int
parent,
int
qstart,
int
qend,
int
k)
{
if
(end < qstart || qend < start) {
return
new
ArrayList<>(
Collections.nCopies(k +
1
, 0L));
}
if
(qstart <= start && qend >= end) {
return
tree.get(parent);
}
int
mid = (start + end) /
2
;
List<Long> left = query(start, mid,
2
* parent +
1
,
qstart, qend, k);
List<Long> right = query(
mid +
1
, end,
2
* parent +
2
, qstart, qend, k);
return
summation(left, right, k);
}
static
void
update(
int
start,
int
end,
int
parent,
int
index, List<Long> updateThis,
int
k)
{
if
(index < start || index > end) {
return
;
}
if
(start == end) {
tree.set(
parent,
summation(updateThis, tree.get(parent), k));
return
;
}
int
mid = (start + end) /
2
;
if
(index > mid) {
update(mid +
1
, end,
2
* parent +
2
, index,
updateThis, k);
}
else
{
update(start, mid,
2
* parent +
1
, index,
updateThis, k);
}
List<Long> left = tree.get(
2
* parent +
1
);
List<Long> right = tree.get(
2
* parent +
2
);
tree.set(parent, summation(left, right, k));
}
static
long
numOfIncSubseqOfSizeK(List<Integer> arr,
int
K)
{
int
n = arr.size();
int
mx = RANKER(arr);
tree =
new
ArrayList<>(Collections.nCopies(
4
* mx +
1
,
new
ArrayList<>(Collections.nCopies(
K +
1
, 0L))));
for
(
int
i =
0
; i < n; i++) {
List<Long> Kj =
new
ArrayList<>(
Collections.nCopies(K +
1
, 0L));
Kj.set(
1
, 1L);
if
(arr.get(i) >
0
) {
List<Long> Ki
= query(
0
, mx,
0
,
0
, arr.get(i) -
1
, K);
for
(
int
k =
2
; k <= K; k++) {
Kj.set(k, Ki.get(k -
1
));
}
}
update(
0
, mx,
0
, arr.get(i), Kj, K);
}
return
tree.get(
0
).get(
K);
}
}