题解:P16236 [蓝桥杯 2026 省 B] LQ 聚合

· · 题解

题目分析

贪心好题。

容易得到对于每个位置 i:

如果是 L:手里的 L 的数量 len++。

如果是 Q:此时每个之前的 L 都可以与当前 Q 形成聚合。

如果是 ?:先看看后面还有多少个 Q(记作 t = a_{i+1}),再看看攒了多少个 L(记作 s = len)。

然后比一下 t 和 s 的大小:

如果 t > s:把这个 ? 变成 L。如果 t \le s:那就把它变成 Q。

证明难度不大

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