51nod 1153 选择子序列 贪心/单调栈

1153 选择子序列
题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
收藏
关注
长度为N的整数数组A,所有的数均不相同,假设下标从0开始。找到一个最长的数组B,B数组的长度为K,数值范围是0 - N - 1,记录的是A数组的下标。满足A[B[0]] > A[B[1]] > A[B[2]] >...A[B[K]],并且对任意连续的两项B[i]及B[i + 1],满足min(B[i],B[i + 1]) < j < max(B[i],B[i + 1]) 均有A[j] < A[B[i + 1]] ,求最大的K。例如:9, 10, 2, -1, 3, -5, 0, -3, 1, 12, 5, 8, -2, 6, 4。可以选出:12, 10, 3, 1, 0, -3。对应的下标为:9, 1, 4, 8, 6, 7(就是B数组),输出6。
Input
第1行:一个数N,表示A数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数对应A数组的元素Ai(0 < Ai < 10^9)
Output
输出B数组最长的长度K。
Input示例
15
9
10
2
-1
3
-5
0
-3
1
12
5
8
-2
6
4
Output示例
6
 
    
思路1:贪心
最大值肯定要取,然后在最大值左右区间找最大值,因为区间不可能交叉,所以找到最大值 左右区间选取数的个数 比较大小,大的就是结果。
用了RMQ维护区间最大值。
Code:
#include 
#define LL long long 
using namespace std;
const int AX = 1e5+66;
struct Node{
	LL v,id;
}dp[AX][20];

int n;
void RMQ(){
	for( int j = 1 ; (1 << j) <= n ; j ++ ){
		for( int i = 0 ; i + (1< dp[i+(1<<(j-1))][j-1].v ){
				dp[i][j].v = dp[i][j-1].v;
				dp[i][j].id = dp[i][j-1].id;
			}else{
				dp[i][j].v = dp[i+(1<<(j-1))][j-1].v;
				dp[i][j].id = dp[i+(1<<(j-1))][j-1].id;
			}
		}
	}
}

Node query( int l , int r ){
	int k = (int)(log(r-l+1)/log(2));
	return ( dp[l][k].v > dp[r-(1< r ) return 0;
	Node tmp = query( l , r );
	return max( dfs( l, tmp.id - 1 ) , dfs( tmp.id + 1 , r ) ) + 1 ;
}

int main(){
	cin >> n ;
	for( int i = 0 ; i < n ; i++ ){
		cin >> dp[i][0].v;
		dp[i][0].id = i;
	}
	RMQ();
	int res = dfs( 0 , n - 1 );
	cout << res << endl;
	return 0 ;
}
思路2:单调栈,结构体除了记录值外,还要记录每个数添加时的最大长度。加入一个数时,如果大于栈顶元素,直接加入,并且更新加入数的最大长度为当前栈内元素个数+1.如果小于栈顶元素,那么就一直弹出,同时还要记录弹出的元素的最大长度(因为可以保留最大长度的那个数,再加入这个数,也是合法的)。最后更新加入数所能达到的最大长度。
Code:
#include 
using namespace std;
const int AX = 1e5+66;
struct Node
{
	int v,len;
}a[AX];
stacks;
int main(){
	int n ;
	cin >> n ;
	int res = 0 ;
	for( int i = 0 ; i < n ; i++ ){
		cin >> a[i].v;
		int tmp = 0 ;
		while( !s.empty() ){
			int t = s.top();
			if( a[i].v > a[t].v ){
				tmp = max( tmp , a[t].len );
				s.pop();
			}else break;
		}
		tmp ++;
		int size = s.size();
		tmp = max( tmp , size + 1 );
		a[i].len = tmp;
		res = max( res , a[i].len ); 
		s.push(i);
	}
	cout << res << endl;
	return 0 ;
}


你可能感兴趣的:(RMQ,贪心)