CodeForces 547B(单调栈)

题目地址:http://codeforces.com/problemset/problem/547/B

题意:有一个长度为n的序列,序列有长度为1...n的连续子序列,一个连续子序列里面最小的值称作这个子序列的子序列的strength,要求出每种长度的连续子序列的最大的strength。

做法:我们可以求出每一个数所在的一个区间,使得这个区间里面该数是最小的。那么,对于每个长度i(1<=i<=n),总有一个数所在的这种区间是i。那么对于一种长度为i的连续子序列,Strength就可以从这些数里面求出来。那么,问题是:如何求出一个数所在的区间使得那个数是最小的呢。答案就是单调栈。单调栈就是一个数字是单调的栈(单调递增或者单调递减)。在这道题,需要一个单调递增的单调栈。这样,我们可以求出那个区间的左端点和右端点,这样得到那个区间的长度。由于对于一个长度i,长度为i-1的子序列的最大的Strength肯定是大于等于长度为i的连续子序列的strength,所以假如一个数为num[i],所得的区间长度是len,那么先做标记ans[len]=max(ans[len],num[i]),然后对于所有数都标记完之后,对于ans数组从后往前递推ans[i]=max(ans[i],ans[i+1])。可以这样做是因为对于一个数,所在的区间长度为len,其实它所在的区间长度还可以是1...len,所以从后往前推是可以的。


#define	_CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <cstring>
#include <climits>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <list>
#include <map>
#include <set>
#include <utility>
#include <sstream>
#include <complex>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <functional>
#include <algorithm>
typedef long long LL;
using namespace std;

const int maxn=200005;
int sta[maxn];//用数组表示栈
int num[maxn],l[maxn],r[maxn];
int maxed[maxn];//maxed[i]是指长度为i的连续子序列的最大strength

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) 
	{
		scanf("%d",&num[i]);
	}	int ptr=1;
	sta[1]=1;l[1]=0,r[1]=n+1;//l[i]代表一个数所在区间的左端点,r[i]代表右端点
	for(int i=2;i<=n;i++)
	{
		while(ptr>=1&&num[i]<=num[sta[ptr]])//ptr是单调栈的栈顶下标
		{
			
			int cur=sta[ptr];
			r[cur]=i;
			ptr--;
		}
		if(ptr==0) l[i]=0;
		else l[i]=sta[ptr];
		sta[++ptr]=i;
		r[i]=n+1;
	}
	for(int i=1;i<=n;i++) maxed[i]=-1;
	int track=1;
	for(int i=1;i<=n;i++)
	{
		int len=r[i]-l[i]-1;
		maxed[len]=max(maxed[len],num[i]);
	}
	for(int i=n;i>=1;i--) maxed[i]=max(maxed[i+1],maxed[i]);
	for(int i=1;i<=n;i++) printf("%d ",maxed[i]);

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值