一、题目描述
二、问题简析
2.1 法一: O ( N 2 ) O(N^2) O(N2)
令
d
p
[
i
]
=
dp[i]=
dp[i]= 以
a
i
a_i
ai 结尾的上升子序列的最大长度。
以
a
i
a_i
ai 结尾的上升子序列有两种可能:
- 1、仅有 a i a_i ai 一个元素
- 2、在满足 j < i j < i j<i 且 a j < a i a_j < a_i aj<ai 的以 a j a_j aj 结尾的上升子序列结尾,加上 a i a_i ai
所以,递归方程为:
d p [ i ] = m a x ( 1 , d p [ j ] + 1 ) , j < i a n d a j < a i dp[i]=max(1,dp[j]+1)~~~~~,j<i~and~a_j<a_i dp[i]=max(1,dp[j]+1) ,j<i and aj<ai
最终结果是 d p [ i ] dp[i] dp[i] 的最大值。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int quickin(void)
{
int ret = 0;
bool flag = false;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-') flag = true;
ch = getchar();
}
while (ch >= '0' && ch <= '9' && ch != EOF)
{
ret = ret * 10 + ch - '0';
ch = getchar();
}
if (flag) ret = -ret;
return ret;
}
const int MAX = 5e3 + 3;
int A[MAX], n, dp[MAX];
int main()
{
#ifdef LOCAL
freopen("test.in", "r", stdin);
#endif
n = quickin();
for (int i = 0; i < n; i++)
A[i] = quickin();
int ans = 0;
for (int i = 0; i < n; i++)
{
dp[i] = 1;
for (int j = 0; j < i; j++)
{
if (A[j] < A[i])
dp[i] = max(dp[i], dp[j] + 1);
}
ans = max(ans, dp[i]);
}
cout << ans << endl;
return 0;
}
2.2 法二: O ( N l o g N ) O(NlogN) O(NlogN)
令
d
p
[
i
]
=
dp[i]=
dp[i]= 长度为
i
+
1
i+1
i+1 的上升子序列的末尾元素的最小值。(因为对于相同长度的上升子序列,结尾元素越小,就越有优势)
对于每个
d
p
[
i
]
dp[i]
dp[i],遍历
a
j
a_j
aj,若
i
=
=
0
i==0
i==0 或
a
j
>
d
p
[
i
−
1
]
a_j > dp[i - 1]
aj>dp[i−1],不断更新
d
p
[
i
]
=
m
i
n
(
d
p
[
i
]
,
a
j
)
dp[i]=min(dp[i],a_j)
dp[i]=min(dp[i],aj)。最终,使
d
p
[
i
]
<
I
N
F
dp[i] <INF
dp[i]<INF 的最大的
i
+
1
i+1
i+1 就是所求。如果按这个思路,仍然是
O
(
N
2
)
O(N^2)
O(N2)。
因为
d
p
[
i
]
dp[i]
dp[i] 是升序,所以我们可以选择用二分搜索来优化。遍历
a
j
a_j
aj,在
d
p
[
i
]
dp[i]
dp[i] 中查找首个不小于(lower_bound
)
a
j
a_j
aj 的
d
p
[
i
]
dp[i]
dp[i] ,并赋值
a
j
a_j
aj。最终,使
d
p
[
i
]
<
I
N
F
dp[i] <INF
dp[i]<INF 的最大的
i
+
1
i+1
i+1 就是所求。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int quickin(void)
{
int ret = 0;
bool flag = false;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-') flag = true;
ch = getchar();
}
while (ch >= '0' && ch <= '9' && ch != EOF)
{
ret = ret * 10 + ch - '0';
ch = getchar();
}
if (flag) ret = -ret;
return ret;
}
const int MAX = 5e3 + 3;
const int INF = 1e8;
int A[MAX], n, dp[MAX];
int main()
{
#ifdef LOCAL
freopen("test.in", "r", stdin);
#endif
n = quickin();
for (int i = 0; i < n; i++)
A[i] = quickin();
fill(dp, dp + n, INF);
for (int i = 0; i < n; i++)
{
*lower_bound(dp, dp + n, A[i]) = A[i];
}
cout << lower_bound(dp, dp + n, INF) - dp << endl;
return 0;
}
完