【BZOJ】1669: [Usaco2006 Oct]Hungry Cows飢餓的奶牛 最長上升子序列

Description

Farmer John養了N(1 <= N <= 5,000)頭奶牛,每頭牛都有一個不超過32位二進制數的正整數編號。FJ希望奶牛們在進食前,能按編號從小到大的順序排好隊,但奶牛們從不聽他的話。爲了讓奶牛們養成這個習慣,每次開飯時,FJ從奶牛中順序地挑出一些,這些奶牛的編號必須按挑出的順序遞增。然後FJ讓被挑出的奶牛們喫飯——其他奶牛就只能餓肚子了。 現在,你得到了這一次開飯前隊伍中從前到後所有奶牛的編號。奶牛們想請你計算一下,按照FJ的規定,最多有多少頭奶牛能喫上飯? 比如說,有11頭奶牛按以下順序排好了隊(數字代表奶牛的編號) 2 5 18 3 4 7 10 9 11 8 15 對於這個隊列,最多可以讓7頭奶牛喫上飯,她們的編號分別爲2,3,4,7,10,11,15。隊列2,5,3,10,15是不合法的,因爲第3頭奶牛的編號(3)小於她前面一頭奶牛的編號(5)。

Input

* 第1行: 一個整數,N * 第2..?行: 除了最後一行,每一行都包含恰好20個用空格隔開的整數,依次表 示隊伍中從前到後的奶牛的編號。如果N不能整除20,那麼最後一 行包含的數字不到20個

Output

* 第1行: 輸出按照FJ的規定,最多可以挑出的奶牛的數目

Sample Input

11
2 5 18 3 4 7 10 9 11 8 15

Sample Output

7

HINT

Source

 題解:

  這題……直接dp最長上升子序列。。無聊的我交了單調棧+貪心的nlog……

      O(n^2):

     

#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN=5001;
int a[MAXN],dp[MAXN];
int main(int argc, char *argv[])
{
	int n,m,i,j;
	int ans=0;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		for(j=0;j<i;j++)
		if(a[i]>a[j]) dp[i]=max(dp[i],dp[j]+1);
		ans=max(ans,dp[i]);
	}
	printf("%d\n",ans);
	return 0;
}


O(nlogn):

 

#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN=5001;
int s[MAXN];
int main(int argc, char *argv[])
{
    int n,i,x,l,r,mid;
    int top=0;
    s[0]=-1;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(x>s[top]) s[++top]=x;
        else
        {
            l=0,r=top;
            while(l<r)
            {
                mid=(l+r)/2;
                if(x<=s[mid]) r=mid;
                else l=mid+1;
            }
            s[l]=x;
        }
    }
    printf("%d\n",top);
    return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章