Description
如果有人认为吃东西只需要嘴巴,那就错了。
都知道舌头有这么一个特性,“由简入奢易,由奢如简难”(据好事者考究,此规律也适合许多其他情况)。具体而言,如果是甜食,当你吃的食物不如前面刚吃过的东西甜,就很不爽了。
大宝是一个聪明的美食家,当然深谙此道。一次他来到某小吃一条街,准备从街的一头吃到另一头。为了吃得爽,他大费周章,得到了各种食物的“美味度”。他拒绝不爽的经历,不走回头路而且还要爽歪歪(爽的次数尽量多)。
Input
两行数据。
第一行为一个整数n,表示小吃街上小吃的数量
第二行为n个整数,分别表示n种食物的“美味度”
Output
一个整数,表示吃得爽的次数
Sample Input
10 3 18 7 14 10 12 23 41 16 24
Sample Output
6
分析
这个题目就是一个最长不降子数列,给你一串数,要求你找到他的最长的一个递增子数列,输出他的长度
首先我们考虑用dp做,代码如下
#include <bits/stdc++.h>
using namespace std;
int a[200005],dp[200005];
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++)
cin>>a[i];
for(int i = 0; i <= n; i++)
dp[i] = 1;
for(int i=0;i<n;i++)
for(int j=0;j<i;j++)
if(a[j]<a[i])
dp[i]=max(dp[i],dp[j]+1);
int maxn=0;
for(int j=0;j<n;j++)
if(dp[j]>maxn)
maxn=dp[j];
cout<<maxn<<endl;
}
return 0 ;
}
但是
超时
因为时间复杂度为O(n^2)
然后我们需要优化算法降低时间复杂度
这里考虑用二分,将时间复杂度降到n*longn
代码
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define N 1000005
#define ll long long
using namespace std;
int num[200005];
int head;
int main()
{
int t;
while(~scanf("%d",&t))
{
head = 1;
for (int i = 1; i <= t; i++)
{
int x;
scanf("%d", &x);
if (head == 1 || num[head - 1] <= x)
{
num[head] = x;
head++;
}
else
{
int min = 1, max = head - 1, mid;
while(max>=min)
{
mid = (max + min) / 2;
if (num[mid] > x)max = mid - 1;
else if (num[mid] <= x)min = mid + 1;
}
num[max+1] = x;
}
}
printf("%d\n", head - 1);
}
return 0;
}