定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素。
注意d中元素是单调递增的,下面要用到这个性质。
首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];
否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]
#include <stdio.h>
#include <string.h>
#include <iostream>
int a[1010];
int d[1010];
int kill(int len, int x)
{
int b = 1, e = len;
while(b <= e)
{
int mid = (b + e) / 2;
if(x > d[mid])
{
b = mid + 1;
}
else{
e = mid - 1;
}
}
return b;
}
int main()
{
int n;
while(!scanf("%d", &n))
{
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
d[1] = a[1];
int len = 1;
int j;
for(int i = 2; i <= n; i++)
{
if(d[1] >= a[i])
{
j = 1;
}
else if(a[i] > d[len])
{
j = ++len;
}
else{
j = kill(len, a[i]);
}
d[j] = a[i];
}
printf("%d\n", len);
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
int n;
int a[MAXN];
int dp[MAXN];
int lis()
{
memset(dp, 0, sizeof(int)*n);
int len = 1;
dp[0] = a[0];
for (int i = 1; i < n; ++i)
{
int pos = lower_bound(dp, dp + len, a[i]) - dp;
dp[pos] = a[i];
// printf("%d %d\n",dp[pos], len);
len = max(len, pos + 1);
}
return len;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
//printf("%d\n", lis());
int len = lis();
for(int i = 0; i < len; i++)
{
printf("%d ", dp[i]);
}
}
LICS
#include <string.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int f[1005][1005], a[1005], b[1005], i, j, t, n1, n2, maxn;
int main()
{
scanf("%d%d", &n1, &n2);
for(i =0; i <= n1; i++)
{
scanf("%d", &a[i]);
}
for(i = 1; i <= n2; i++)
{
scanf("%d", &b[i]);
}
memset(f, 0, sizeof(f));
for(i = 1; i <= n1; i++)
{
maxn = 0;
for(j = 1; j <= n2; j++)
{
f[i][j] = f[i - 1][j];
if(a[i] > b[j] && maxn < f[i - 1][j])
{
maxn = f[i - 1][j];
}
if(a[i] == b[j])
{
f[i][j] = maxn + 1;
}
}
}
maxn = 0;
for(i = 1; i <= n2; i++)
{
if(maxn < f[n1][i])
{
maxn = f[n1][i];
}
}
printf("%d\n", maxn);
}