您的位置:首页 > 其它

牛客网 D-YB要打炉石 最大上升子序列

2018-01-31 13:12 239 查看
链接:https://www.nowcoder.com/acm/contest/74/D

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K

64bit IO Format: %lld

题目描述

Wozuinb非常喜欢打炉石传说,但是菜的不行,所以他决定打
竞技场来练练手。系统按顺序给出n张卡牌,每张卡牌都有自
己的使用消耗a[i],每次只给出一张,wozuinb可以选择或者
弃掉这张牌。每选择一张牌都会按选择顺序放在卡槽中,当
卡槽中放满30张即可组成一套套牌。Wozuinb希望自己的套牌的
消耗满足一个平滑的曲线,即30张卡牌都满足第i张卡牌的消耗
不小于第i-1张(i>1)。请你帮助wozuinb看一看,这些卡牌能不
能组成想要的套牌,如果能组成输出“yes”,如果不能输出“no”。


输入描述:

第一行输入一个整数n,0<n<100。
第二行输入一行数字a[i],每个数字用空格隔开,代表第i张出现的卡牌的消耗。

输出描述:

输出一行,“yes”或“no”


这道题目就是求最大上升子序列长度,不过可以大于等于, 非递减即可

#include <iostream>
#include <cstdio>
using namespace std ;
int dp[101] , a[101] , n ;

int main(){
int n ;
scanf( "%d" , &n ) ;
for( int i = 1 ; i <= n ; ++i )
scanf( "%d" , &a[i] ) , dp[i] = 1 ;
if( n < 30 ){
cout << "no" << endl ;
return 0 ;
}
for( int i = 2 ; i <= n ; ++i )
for( int j = 1 ; j < i ; ++j )
if( a[i] >= a[j] )
dp[i] = max( dp[i] , dp[j] + 1 ) ;
int ans = dp[1] ;
for( int i = 2 ; i <= n ; ++i )
ans = max( ans , dp[i] ) ;
printf( ans >= 30 ? "yes\n" : "no\n" ) ;
return 0 ;
}
因为题目数据很小,长度才 100,以上的时间复杂度是 O(n^2)的。
求最大上升子序列还有一种O(nlogn)的解法,利用到了二分搜索。

#include <iostream>
#include <cstdio>
using namespace std ;
int a[101] ;
int package[101] , top ;

int LCS( int *a , int n ){
top = 0 ;
for( int i = 1 ; i <= n ; ++i ){
if( top == 0 || package[top] <= a[i] )  // 当前上升子序列的最大值 < a[i]
package[++top] = a[i] ;            // 上升子序列扩张
else{
int l = 1 , r = top ;              // 当前a[i] < 上升子序列的最大值
while( l <= r ){
int mid = ( r + l ) >> 1 ;     // 二分找到当前上升子序列中第一个大于 a[i]的位置
if( a[i] < package[mid] )
r = mid - 1 ;
else
l = mid + 1 ;
}
package[l] = a[i] ;  // 将 更大的数字替换成更小的数字,增加了上升子序列扩张的可能性
}                        // 保证未来的上升子序列 >= 原来的
}
return top ;                 // 返回最大上升子序列长度 复杂度 O(nlogn)
}

int main(){
int n ;
cin >> n ;
for( int i = 1 ; i <= n ; ++i )
cin >> a[i] ;
if( n < 30 ){
cout << "no" << endl ;
return 0 ;
}
printf( LCS( a , n ) >= 30 ? "yes\n" : "no\n" ) ;
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐