【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; }