洛谷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;
}

浙公网安备 33010602011771号