题解:P16236 [蓝桥杯 2026 省 B] LQ 聚合
题目分析
贪心好题。
容易得到对于每个位置
如果是 L:手里的 L 的数量 len++。
如果是 Q:此时每个之前的 L 都可以与当前 Q 形成聚合。
如果是 ?:先看看后面还有多少个 Q(记作 L(记作
然后比一下
如果 ? 变成 L。如果 Q。
证明难度不大
- 修复为
L的条件t > s 意味着后续Q的数量更多,优先增加L能最大化未来配对数。 - 修复为
Q的条件t \le s 意味着当前L的数量足够,立即形成聚合更优。
AC 代码
#include <bits/stdc++.h>
int a[100009]; // 存储每个位置之后 Q 的数量
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n; // 输入序列长度
string s;
cin >> s;
a[n] = 0; // 边界条件:末尾之后没有 Q
for (int i = n - 1; i >= 0; i--) {
a[i] = a[i + 1];
if (s[i] == 'Q') {
a[i]++;
}
}
ll ans = 0, len = 0, weizhi = 0; // ans:答案,len:当前 L 数量,weizhi:初始问号数量
for (char c : s) {
if (c == '?') {
weizhi++; // 统计问号总数
}
}
int yizhi = weizhi; // 剩余问号数量(用于遍历时更新)
for (int i = 0; i < n; i++) { // 遍历序列并决策
if (s[i] == 'L') {
len++; // 遇到 L,增加 L 数量
} else if (s[i] == 'Q') {
ans += len; // 遇到 Q,累加聚合数
} else if (s[i] == '?') { // 处理问号
ll t = a[i + 1] + (yizhi - 1), s = len; // t:后续 Q 数量,s:当前 L 数量
if (t > s) { // 条件满足时修复为 L
len++;
} else { // 否则修复为 Q
ans += len;
}
yizhi--; // 剩余问号数减一
}
}
cout << ans << endl; // 输出答案
return 0;
}