Oliver的恋爱

18年第一次信心赛t3Oliver的恋爱❤

来自 liyifeng编程普及系列

题目描述

当Oliver当上年级第一时,许多女孩开始注意他,而Oliver却只喜欢小X,因为她很独特。如果Oliver和她在一起的那天跟上次Oliver和他在一起那天一样高兴,或更高兴,她就会对Oliver很好,相反,如果她比上次不高兴,就会对Oliver很凶(汗~~)!所以Oliver又找哆啦A梦借了台机器,它能知道小X在N天里每天的高兴度M。所以,Oliver想知道,在这N天中,如果要使每次和小X在一起时都使小X对他好,那么在N天中,最多能和小X在一起多少天。

输入输出格式

输入格式:

共2行,第一行为一个N,第二行为N个数,为小X每天的高兴程度M。

输出格式:

共1个数,为Oliver最多能和小X在一起多少天。

输入输出样例

输入样例#1: 复制
5                  
2 3 5 6 4 
输出样例#1: 复制
4

说明

数据规模与约定

对于30%的数据,N<=8000,

对于100%的数据,N<=27000,M<31000.

题解:

本题为最长不下降子序列的模板;需使用使用的是nlogn的做法;

该模板中使用c++的STL库中的upper_bound,省去了不少的麻烦(所以说STL大法好)(~ ̄▽ ̄)~

用数组a储存输入的数据,dp储存最长不下降子序列,cd为序列的长度;

具体思想:首先令dp【1】=a【1】,这样a【1】便成为了该序列的开头元素(即该序列的最小元素);

然后从2到n开始循环,当a【i】>dp[cd]时,通过dp【++cd】=a【i】来使a【i】加入该序列;

关键来了:当a【i】

首先我们需要的是一个最长的不下降的子序列,但我们当然想增加的越慢越好;

比如 队列中为{3,4, 7}这时下一个出现的元素是5,那肯定是要把7替换为5,这样的话不但序列的长度没有缩短

而且5比7有着更大的潜力,5后面可以接6,而7就不行;因此碰见a【i】时我们要将序列中第一个大于a【i】的数替换为a【i】;

那么问题来了 ——我们要怎样才能迅速地找到这样的数呢?

这就需要我们的STL库中的upper_bound了!而它每次的复杂度为logn问题就解决了!

最后dp的长度便是该题的答案!




具体代码如下:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
int dp[100010];
int a[100010];
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	  scanf("%d",&a[i]);
	dp[1]=a[1];
	int cd=1;
	for(int i=2;i<=n;i++)
	   {
	   	if(a[i]>=dp[cd])
	   	{
	   		dp[++cd]=a[i];//先cd++;然后再dp【cd】=a【i】;
	   	}
	   	else {
	   		  int j=upper_bound(dp+1,dp+cd+1,a[i])-dp; //找到第一个大于a【i】的数的下标
	   		  dp[j]=a[i];
	   	     }
	   }  
	   printf("%d",cd);//输出结果
	   return 0;
}



你可能感兴趣的:(noip)