1 条题解
-
0
📘 中文题目解析(逆向自代码)
给定一个长度为 $n$ 的字符串,由
'T'
、'W'
以及其他字符组成。每个字符对应一定的得分:- 其他字符得 $+1$ 分;
'T'
额外加 $1$ 分(即共 $2$ 分);'W'
虽然本身得 $+1$,但程序将其视为“惩罚项”,通过删除两侧的'W'
来降低分数,使得可得偶数分。
你可以从字符串中选择一个连续子串(区间),问是否存在某个区间其总分恰好等于给定的查询值 $x$,如果有,输出该区间的左右端点 $[l, r]$,否则输出
NIE
。
🧠 解题思路
-
预处理最大奇数分和偶数分:
- 从全串开始,计算最大得分(默认包含全部字符);
- 然后尝试删除一对
'W'
字符,使得得分变为偶数(因为删一对'W'
相当于总分减 $2$)。
-
构造所有可能的得分:
- 每次减少两端某个字符(优先去
'W'
或'T'
)来降低得分; - 维护每个得分值对应的区间起止位置。
- 每次减少两端某个字符(优先去
-
回答查询:
- 如果查询的得分超出最大得分范围,或奇偶性不匹配,则输出
NIE
; - 否则输出其对应的左右区间。
- 如果查询的得分超出最大得分范围,或奇偶性不匹配,则输出
🧾 注释版完整 C++ 代码
#include <bits/stdc++.h> #define rep(i,x,y) for (int i=(x);i<=(y);i++) using namespace std; const int N = 2e6 + 100; int n, m; int sum1, sum2; // sum1 表示最大奇数得分,sum2 表示最大偶数得分 int l1, r1, l2, r2; // 区间左右端点 int l[N], r[N]; // 每个得分值 x 的区间 [l[x], r[x]] char str[N]; // 存储输入字符串 int main() { scanf("%d%d%s", &n, &m, str + 1); // 从下标1开始读入 // 计算最大总得分:每个字符1分,若为'T'再多加1分 rep(i, 1, n) sum1 += 1 + (str[i] == 'T'); l1 = 1, r1 = n; // 尝试删除一个W(从左开始),看能不能得到更小的偶数得分 rep(i, 1, n) { if (str[i] == 'W') { sum2 = max(sum2, sum1 - i * 2 + 1); // 去掉前 i 个字符造成的减分 l2 = i + 1, r2 = n; break; } } // 从右开始找W for (int i = n; i; i--) { if (str[i] == 'W') { if (sum1 - (n - i) * 2 - 1 > sum2) { sum2 = sum1 - (n - i) * 2 - 1; l2 = 1, r2 = i - 1; } break; } } // 如果 sum1 是偶数,交换使 sum1 始终为奇数得分最大值 if (!(sum1 & 1)) swap(sum1, sum2), swap(l1, l2), swap(r1, r2); // 从最大奇数分开始,倒推构造每个奇数得分对应的区间 for (int i = sum1; i >= 1; i -= 2) { l[i] = l1, r[i] = r1; if (str[l1] == 'W' && str[r1] == 'W') l1++, r1--; // 两端都是W,去掉两个 else if (str[l1] == 'T') l1++; // T为2分,优先去掉 else r1--; // 否则去掉右端 } // 同理处理偶数分数 for (int i = sum2; i >= 1; i -= 2) { l[i] = l2, r[i] = r2; if (str[l2] == 'W' && str[r2] == 'W') l2++, r2--; else if (str[l2] == 'T') l2++; else r2--; } // 回答每个查询 while (m--) { int x; scanf("%d", &x); // 如果 x 奇偶性不对 或 超过可达最大值,输出NIE if ((x & 1) && x > sum1 || !(x & 1) && x > sum2) puts("NIE"); else printf("%d %d\n", l[x], r[x]); } return 0; }
✅ 输入输出样例说明
输入:
12 3 TWTTWTTWTWTW 3 10 13
输出:
1 2 NIE 1 9
解释:
- 最大奇数得分是 13(如前9个字符),所以可以构造出 13、11、9、... 的区间;
- 最大偶数得分是 10(去掉左右两端的W),所以可以构造出 10、8、6、... 的区间;
- 查询 3:在奇数序列中存在 → 输出区间;
- 查询 10:在偶数序列中存在 → 输出区间;
- 查询 13:最大奇数得分 → 输出对应区间。
如你需要将此题改写成 Python 实现,或构造测试生成器,也可以继续告诉我。
- 1
信息
- ID
- 2515
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者