洛谷P3564 BAR-Salad Bar

洛谷P3564 BAR-Salad Bar

题目链接


题目大意

  • 有一个长度为 \(n\) 的字符串,每一位只会是 \(\texttt{p}\)\(\texttt{j}\)。求一个最长子串,使得不管是从左往右还是从右往左取,都保证每时每刻已取出的 \(\texttt{p}\) 的个数不小于 \(\texttt{j}\) 的个数。
  • \(1\leq n\leq10^6\)

题解
把所有 \(\texttt{p}\) 标记为 \(1\),把所有 \(\texttt{j}\) 标记为 \(-1\),记录前缀和数组 \(s\)
对一个区间 \([l,r]\)\(\forall i\in[l,r]\),必有 \(s_l\leq s_i\leq s_r\)
所以对每一个 \(i\) 求出对应的最远的满足条件的长度就行了。


代码

#include <bits/stdc++.h>
using namespace std;
#define res register int
#define LL long long
#define inf 0x3f3f3f3f
#define eps 1e-15
const int N = 1e6 + 10;
int n, s[N], minx;
int head[N], nxt[N], to[N];
char str[N];
int main()
{
    memset(head, -1, sizeof(head));
    cin >> n;
    scanf("%s", str + 1);
    for (res i = 1; i <= n; i++)
    {
        s[i] = s[i - 1] + (str[i] == 'p' ? 1 : -1);
        minx = min(minx, s[i]);
    }
    for (res i = n; i >= 0; i--)
    {
        res x = s[i] - minx;
        nxt[i] = head[x], head[x] = i, to[i] = i;
    }
    res ans = 0;
    for (res i = n, pre = n; i >= 1; i--)
    {
        if (str[i] == 'j')
            pre = i - 1;
        else
        {
            if (nxt[i - 1] >= 0 && s[to[nxt[i - 1]]] >= s[pre])
                pre = to[nxt[i - 1]];
            to[i - 1] = pre;
            res pos = pre - i + 1;
            ans = max(pos, ans);
        }
    }
    cout << ans;
    return 0;
}
posted @ 2021-02-03 22:04  cymrain07  阅读(54)  评论(0)    收藏  举报
\