题目链接:点击打开链接
题目大意:略
题目分析:1.用n平方的做法,枚举以data【i】为结尾的子序列,向前查找,比data【i】小并且dp【j】比dp【i】小的
新手代码:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1005;
int data[maxn],dp[maxn];
int main()
{
int n,i,j,ans;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++)
scanf("%d",&data[i]);
ans=1;
for(i=0;i<n;i++)
{ dp[i]=1;//注意!!
for(j=i;j>=0;j--)
if(data[j]<data[i]&&dp[j]+1>dp[i]){dp[i]=dp[j]+1;}
if(dp[i]>ans) ans=dp[i];
}
printf("%d\n",ans);
}
return 0;
}
测试样例
5
1 2 1 4 1
6
1 1 2 2 1 1
6
1 6 2 3 7 5
2. 二分法nlogn+栈+替换 参考:点击打开链接
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=1005;
int stack[maxn];
int main()
{
int n,i,top,data,j;
while(~scanf("%d",&n))
{
top=0;stack[0]=-1;//注意栈首
for(i=0;i<n;i++)
{
scanf("%d",&data);
if(data>stack[top]) stack[++top]=data;
else
{
int l=1,r=top,mid;
while(l<=r)
{
mid=(l+r)/2;
if(data>stack[mid]) l=mid+1;
else r=mid-1;
}
stack[l]=data;
}
}
printf("%d\n",top);
}
}
备注:这种方法适用于求数目,没有真正求出具体的字串
除此之外:其实不用栈
使用函数lower_bound()
函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置
举例如下:
一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标
则
pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。
pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。
pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。
所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~
返回查找元素的第一个可安插位置,也就是“ 元素值>=查找值”的第一个元素的位置关于lower_bound() 详见:点击打开链接
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define max 10005
using namespace std;
int main()
{
int data[max],a[max],n,i;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&data[i]);
}
int top=0;a[top]=-1;
for(i=1;i<=n;i++)
{
if(data[i]>a[top])
a[++top]=data[i];
else
{
int pos=lower_bound(a+1,a+1+top,data[i])-a;
a[pos]=data[i];
}
}
printf("%d\n",top);
return 0;
}