您的位置:首页 > 其它

单调递增子序列(二)(nyoj 214)

2014-04-08 21:49 197 查看


单调递增子序列(二)

时间限制:1000 ms | 内存限制:65535 KB
难度:4

描述

给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。

如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。

输入有多组测试数据(<=7)

每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。

数据以EOF结束 。

输入数据保证合法(全为int型整数)!
输出对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
样例输入
7
1 9 10 5 11 2 13
2
2 -1


样例输出
5
1


这个题我理解了有一会= =。

觉得这个写的还不错---->点击打开链接

程序中的dp数组不再是存一个数值来代表最大的长度,而是存储到目前为止的最长的递增子序列的那个序列,由下标k来控制,所以k的值就代表了递增子序列的长度。

#include <stdio.h>
#define N 100010

int a
, dp
;
//dp[i]表示序列长度为i是序列的最后一个元素的最小值

void answer(int n)
{
int low, high, mid, i, k = 2;
dp[1] = a[1];

for(i = 2; i <= n; i++)
{
if(dp[k - 1] < a[i])//如果a[i]比dp[k-1]大,那么就表示a[i]可以直接接在序列的后面构成新的序列
dp[k ++] = a[i];
else
{//否则运用二分法较快速在dp[low]中找到a[i]能插入的地i方
//满足dp[low]<a[i]且low是满足条件的最大值 ,这样dp[low] < a[i] <= dp[low + 1],再将a[i]替换dp[low + 1],因为当子序列长度一样时,序列最后一					 //个元素选择小的那个元素会产生更长的子序列
low = 1;
high= k;
while(low <= high)
{
mid = (low + high) / 2;
if(a[i] < dp[mid])
high = mid - 1;
else
low = mid + 1;
}
//替换
dp[low] = a[i];
}
}
/*
for(i = 1; i <= n; i++)
printf("%d   ", dp[i]);
printf("\n");
*/
printf("%d\n", k - 1);
}

int main (void)
{
int n;
while(scanf("%d", &n) != EOF)
{
int i;
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
answer(n);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: