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

链接: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 ;  
}  






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值