题解 P6510 【奶牛排队】
【单调栈】【P6510】奶牛排队
Analysis
怎么还有分治 RMQ 那么神仙的做法啊 /fad。
考虑枚举右端点
因为
考虑用单调栈来维护当前序列的后缀最大最小值,每次新枚举到一个
下面说明如何用单调栈维护后缀最值:
因为最大值的方法与最小值基本相同,因此这里只考虑维护最大值。考虑用一个栈来维护当前序列的所有后缀最大值所在的位置的下标。当序列新加入一个元素时,一直弹栈直到栈顶元素所对应的值大于新元素,然后将新元素压入栈中即可。
while (tx && a[sx[tx]] < a[i]) --tx;
sx[++tx] = i;
Code
#include <cstdio>
#include <set>
#include <algorithm>
const int maxn = 100005;
int n, ans, tx, tn;
int a[maxn], sx[maxn], sn[maxn];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", a + i);
for (int i = 1; i <= n; ++i) {
while (tn && a[sn[tn]] >= a[i]) --tn;
while (tx && a[sx[tx]] < a[i]) --tx;
int k = std::upper_bound(sn + 1, sn + 1 + tn, sx[tx]) - sn;
if (k != (tn + 1)) {
ans = std::max(ans, i - sn[k] + 1);
}
sn[++tn] = i;
sx[++tx] = i;
}
printf("%d\n", ans);
return 0;
}