import
java.util.*;
import
java.io.*;
public
class
GFG{
public
static
int
M =
100000
;
public
static
ArrayList<ArrayList<Integer>> tree =
new
ArrayList<ArrayList<Integer>>();
public
static
void
update_tree(
int
start,
int
end,
int
update_idx,
int
length_t,
int
count_c,
int
idx)
{
if
(start == end && start == update_idx) {
tree.get(idx).set(
0
, Math.max(tree.get(idx).get(
0
), length_t));
tree.get(idx).set(
1
, count_c);
return
;
}
if
(update_idx < start || end < update_idx) {
return
;
}
int
mid = (start + end) /
2
;
update_tree(start, mid, update_idx,
length_t, count_c,
2
* idx);
update_tree(mid +
1
, end, update_idx,
length_t, count_c,
2
* idx +
1
);
if
(tree.get(
2
* idx).get(
0
) == tree.get(
2
* idx +
1
).get(
0
)) {
tree.set(idx,
new
ArrayList<Integer>(
List.of(tree.get(
2
* idx).get(
0
),
tree.get(
2
* idx).get(
1
) +
tree.get(
2
* idx +
1
).get(
1
))
));
}
else
if
(tree.get(
2
* idx).get(
0
) > tree.get(
2
* idx +
1
).get(
0
)) {
tree.set(idx,
new
ArrayList<Integer>(
List.of(tree.get(
2
* idx).get(
0
), tree.get(
2
* idx).get(
1
))
));
}
else
{
tree.set(idx,
new
ArrayList<Integer>(
List.of(tree.get(
2
* idx +
1
).get(
0
), tree.get(
2
* idx +
1
).get(
1
))
));
}
}
public
static
ArrayList<Integer> query(
int
start,
int
end,
int
query_start,
int
query_end,
int
idx)
{
if
(query_start <= start && end <= query_end) {
return
new
ArrayList<Integer>(tree.get(idx));
}
ArrayList<Integer> temp =
new
ArrayList<Integer>(
List.of(Integer.MIN_VALUE,
0
)
);
if
(end < query_start || query_end < start) {
return
new
ArrayList<Integer>(temp);
}
int
mid = (start + end) /
2
;
ArrayList<Integer> left_child = query(start, mid,
query_start,
query_end,
2
* idx);
ArrayList<Integer> right_child = query(mid +
1
, end,
query_start,
query_end,
2
* idx +
1
);
if
(left_child.get(
0
) > right_child.get(
0
)) {
return
new
ArrayList<Integer>(left_child);
}
if
(right_child.get(
0
) > left_child.get(
0
)) {
return
new
ArrayList<Integer>(right_child);
}
return
new
ArrayList<Integer>(
List.of(
left_child.get(
0
),
left_child.get(
1
) + right_child.get(
1
)
)
);
}
public
static
int
countLIS(
int
arr[],
int
n)
{
ArrayList<ArrayList<Integer>> pair_array =
new
ArrayList<ArrayList<Integer>>();
for
(
int
i =
0
; i < n ; i++){
pair_array.add(
new
ArrayList<Integer>(
List.of(arr[i], i)
));
}
Collections.sort(pair_array,
new
comp());
for
(
int
i =
0
; i < n ; i++) {
int
update_idx = pair_array.get(i).get(
1
);
if
(update_idx ==
0
) {
update_tree(
0
, n -
1
,
0
,
1
,
1
,
1
);
continue
;
}
ArrayList<Integer> temp = query(
0
, n -
1
,
0
,
update_idx -
1
,
1
);
update_tree(
0
, n -
1
, update_idx, temp.get(
0
) +
1
,
Math.max(
1
, temp.get(
1
)),
1
);
}
ArrayList<Integer> ans = query(
0
, n -
1
,
0
, n -
1
,
1
);
return
ans.get(
1
);
}
public
static
void
main(String args[])
{
int
arr[] = {
1
,
3
,
5
,
4
,
7
};
int
n = arr.length;
for
(
int
i =
0
; i <
4
*M +
1
; i++){
tree.add(
new
ArrayList<Integer>(
List.of(Integer.MIN_VALUE,
0
)
));
}
System.out.println(countLIS(arr, n));
}
}
public
class
comp
implements
Comparator<ArrayList<Integer>>{
public
int
compare(ArrayList<Integer> a, ArrayList<Integer> b)
{
if
(a.get(
0
).equals(b.get(
0
))) {
return
b.get(
1
).compareTo(a.get(
1
));
}
return
a.get(
0
).compareTo(b.get(
0
));
}
}