例题:
题解:该题很数据量很大用传统的动态规划算法写,会TLE,所以需要用二分优化算法,我们可以定义一个栈Stack[]
,可以说是单调栈,利用二分查找,保持栈的单调行,从一层for循环里找到每一个ans
所在的位置
以样例1为例:
1 9 10 5 11 2 13
Stack[1]=a[0]先把第一个值入栈
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
1 | 9 | 10 | 11 | 13 |
这是最大的递增子序列,而二分思路是记录了a[ ]
中每一个的位置
主要操作:
一开始先入栈
Stack:[1][9][10]第四个数5二分查找它的位置是2,替代9此时说明以5为尾的最大长度是2,之后不断更
新入栈多少个最大长度就是top的大小
AC代码:
#include<bits/stdc++.h>
using namespace std;
//二分优化最长递增子序列
#define maxn 100005
int Stack[maxn];
int a[maxn];
int n;
int lower_ans(int l,int r,int i)//返回刚好比l大1的位置
{
while(l<=r)
{
int mid=(l+r)/2;
if(a[i]<Stack[mid])
{
r=mid-1;
}
else
{
l=mid+1;
}
}
return l;
}
void slove_dp()
{
int top=1;
Stack[top]=a[0];
for(int i=1; i<n; i++)
{
if(Stack[top]<a[i])
{
Stack[++top]=a[i];//保证Stack[]单调
}
else
{
Stack[lower_ans(1,top,i)]=a[i];
}
}
printf("%d\n",top);
}
int main()
{
while(~scanf("%d",&n))
{
memset(Stack,0,sizeof(Stack));
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
slove_dp();
}
}