using
System;
using
System.Collections.Generic;
using
System.Linq;
class
LIS {
public
static
int
Ranker(
int
[] nums) {
int
n = nums.Length;
int
[] temp = nums.ToArray();
Array.Sort(temp);
Dictionary<
int
,
int
> rank =
new
Dictionary<
int
,
int
>();
int
mx = 0;
for
(
int
i = 0; i < n; i++) {
if
(!rank.ContainsKey(temp[i])) {
rank[temp[i]] = mx;
mx++;
}
}
for
(
int
i = 0; i < n; i++) {
nums[i] = rank[nums[i]];
}
return
mx;
}
public
static
int
[] ChooseBest(
int
[] left,
int
[] right) {
int
mxLen_LFT = left[0];
int
ways_LFT = left[1];
int
mxLen_RHT = right[0];
int
ways_RHT = right[1];
if
(mxLen_LFT > mxLen_RHT) {
return
new
int
[] { mxLen_LFT, ways_LFT };
}
else
if
(mxLen_LFT < mxLen_RHT) {
return
new
int
[] { mxLen_RHT, ways_RHT };
}
else
{
return
new
int
[] { mxLen_LFT, ways_LFT + ways_RHT };
}
}
public
static
void
Update(
int
start,
int
end,
int
parent,
int
element,
int
mxLength,
int
ways,
int
[][] tree) {
if
(start == end) {
if
(tree[parent][0] == mxLength) {
tree[parent][1] += ways;
}
else
{
tree[parent][0] = mxLength;
tree[parent][1] = ways;
}
return
;
}
int
mid = (start + end) / 2;
if
(element <= mid) {
Update(start, mid, 2 * parent + 1, element, mxLength, ways, tree);
}
else
{
Update(mid + 1, end, 2 * parent + 2, element, mxLength, ways, tree);
}
tree[parent] = ChooseBest(tree[2 * parent + 1], tree[2 * parent + 2]);
}
public
static
int
[] MaxLen(
int
start,
int
end,
int
qstart,
int
qend,
int
parent,
int
[][] tree) {
if
(start > qend || end < qstart) {
return
new
int
[] { 0, 0 };
}
if
(start >= qstart && end <= qend) {
return
tree[parent];
}
int
mid = (start + end) / 2;
int
[] left = MaxLen(start, mid, qstart, qend, 2 * parent + 1, tree);
int
[] right = MaxLen(mid + 1, end, qstart, qend, 2 * parent + 2, tree);
return
ChooseBest(left, right);
}
public
static
int
FindNumberOfLIS(
int
[] nums) {
int
n = nums.Length;
int
mx = Ranker(nums);
int
[][] tree =
new
int
[4 * mx + 5][];
for
(
int
i = 0; i < tree.Length; i++) {
tree[i] =
new
int
[2];
}
for
(
int
i = 0; i < n; i++) {
int
mxLen = 1;
int
ways = 1;
if
(nums[i] > 0) {
int
[] info = MaxLen(0, mx, 0, nums[i] - 1, 0, tree);
if
(info[0] + 1 > mxLen) {
mxLen = info[0] + 1;
ways = info[1];
}
}
Update(0, mx, 0, nums[i], mxLen, ways, tree);
}
return
tree[0][1];
}
public
static
void
Main(
string
[] args) {
int
[] arr = {1, 3, 5, 4, 7};
Console.WriteLine(FindNumberOfLIS(arr));
}
}