【bzoj1307】玩具 单调栈

题目描述

小球球是个可爱的孩子,他喜欢玩具,另外小球球有个大大的柜子,里面放满了玩具,由于柜子太高了,每天小球球都会让妈妈从柜子上拿一些玩具放在地板上让小球球玩。 这天,小球球把所有的N辆玩具摆成一排放在地上,对于每辆玩具i,小球球都会给它涂上一个正整数value[i],以表示小球球对该玩具的喜爱程度,value[i]越小则表示他越喜爱。当然对于两辆不同的玩具u,v(u<>v),亦有可能value[i]=value[j],也就是说小球球对u,v两车的喜爱程度是一样的。 小球球很贪玩,他希望能从中间某个位置,连续的取出k辆玩具,使得这k辆车里喜爱程度最大的一辆车的喜爱程度正好等于k,且这k辆车中没有两辆车的喜爱程度是相同的。小球球希望知道k的最大值为多少。

输入

第一行一个整数N,表示小球球拥有的玩具数量。 接下来N行,每行一个整数,表示value[i]。

输出

一个整数k,即答案。

样例输入

6
2
4
1
3
2
1

样例输出

4


题解

单调栈

如果没有value互不相同的要求,那么就是单调栈傻*题,求出一个数左右第一个比它大的数的位置,根据这个区间判断是否有贡献。

那么加上了这个条件呢?其实也是一样的。我们在使用单调栈的同时,使用一个变量维护最后一个出现相同数字的位置,然后区间的交集即为所求区间。再判断贡献即可。

UPD:其实这个做法是错的,然而数据太水可以shi过(好像直接输出最大的value也能过?)

#include <cstdio>
#include <algorithm>
#define N 1000010
using namespace std;
int a[N] , sta[N] , top , last[N] , lp[N] , rp[N];
int main()
{
	int n , i , now , ans = 0;
	scanf("%d" , &n);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
	for(i = 1 , now = 0 ; i <= n ; i ++ )
	{
		while(top && a[i] > a[sta[top]]) top -- ;
		now = max(now , last[a[i]]) , last[a[i]] = i;
		lp[i] = max(sta[top] , now) , sta[++top] = i;
	}
	for(i = 1 ; i <= n ; i ++ ) last[a[i]] = n + 1;
	for(i = n , now = sta[0] = n + 1 , top = 0 ; i ; i -- )
	{
		while(top && a[i] > a[sta[top]]) top -- ;
		now = min(now , last[a[i]]) , last[a[i]] = i;
		rp[i] = min(sta[top] , now) , sta[++top] = i;
	}
	for(i = 1 ; i <= n ; i ++ )
		if(rp[i] - lp[i] > a[i])
			ans = max(ans , a[i]);
	printf("%d\n" , ans);
	return 0;
}

 

 

posted @ 2017-07-10 21:28  GXZlegend  阅读(418)  评论(0编辑  收藏  举报