1 条题解

  • 0
    @ 2025-5-25 18:24:59

    📘 中文题目解析(逆向自代码)

    给定一个长度为 $n$ 的字符串,由 'T''W' 以及其他字符组成。每个字符对应一定的得分:

    • 其他字符得 $+1$ 分;
    • 'T' 额外加 $1$ 分(即共 $2$ 分);
    • 'W' 虽然本身得 $+1$,但程序将其视为“惩罚项”,通过删除两侧的 'W' 来降低分数,使得可得偶数分。

    你可以从字符串中选择一个连续子串(区间),问是否存在某个区间其总分恰好等于给定的查询值 $x$,如果有,输出该区间的左右端点 $[l, r]$,否则输出 NIE


    🧠 解题思路

    1. 预处理最大奇数分和偶数分

      • 从全串开始,计算最大得分(默认包含全部字符);
      • 然后尝试删除一对 'W' 字符,使得得分变为偶数(因为删一对 'W' 相当于总分减 $2$)。
    2. 构造所有可能的得分

      • 每次减少两端某个字符(优先去 'W''T')来降低得分;
      • 维护每个得分值对应的区间起止位置。
    3. 回答查询

      • 如果查询的得分超出最大得分范围,或奇偶性不匹配,则输出 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
    上传者