My Title

找山坡

题意:

母牛哥在电脑面前坐久了,想站起来看看窗外的小山坡,于是就想出了这个问题:

给定一个大小为n的数组a,序号从1开始,

计算:max{ R - L | 1 <= L <= R <= n, a[L] == a[R], 对于所有i (L <= i <= R), 满足a[i] >= a[L] }.

也就是找到两个坐标,这两个坐标的值相等,并且他们之间的值都大于等于这两个坐标上的值.
这两个坐标相减最大能是多少.
示例
输入
5
1 2 3 2 1
输出
4
(当L=1,R=5时,满足题目条件的最优解,答案为R-L=5-1=4)

数据范围:

1<=n<=1e6

0<=a[i]<=1e9

思路:
法一:用单调栈维护一个单调递增区间,然后当栈顶与当前的数相等时取坐标差,比较得最大值。
    for(int i=1; i<=n; i++){
        a[i]=read();
        while(top && a[stk[top]]>a[i]) top--;    //此时存的是单调递增
        if(!top) stk[++top]=i;
        else{
            if(a[stk[top]]==a[i]) ans = max(ans, i-stk[top]);
            else stk[++top]=i;
        }
    }
View Code

思路二:这是我最开始的思路,用双指针维护,思路其实同法一,但是双指针维护的 l 和 r 的关系,应该维护的是一个单调栈而不是单调队列,故想法错误。

//错误的代码
    for(int l=1,r=1; r<=n; r++){
        while(l<r && a[r]<a[l]) l++;
        if(a[r]==a[l]) ans = max(ans, r-l);
    }

/*
eg:
1 2 4 5 3 10 1
*/
View Code

法二:

用RMQ 存区间最小值,然后离散化存某个数上一次出现的位置。扫描一遍,如果该数已出现过,就检测两个数的区间内最小值是否为这个数。
可以用线段树维护区间最值,也可以用ST表。
(看rank榜上别人的思路,自己就没有写一遍了hh)

posted @ 2022-03-03 11:42  EvfX  阅读(32)  评论(0编辑  收藏  举报