1 条题解

  • 0
    @ 2025-10-16 13:48:33

    题解说明

    问题背景:
    给定一个字符串,要求将其中的所有 'a' 字符重新排列,使得它们在字符串中关于中心对称。允许的操作是移动 'a' 的位置,代价为移动距离。目标是计算最小的总移动距离。如果无法形成对称排列,则输出 -1

    核心思路:

    1.1. 收集 'a' 的位置:

    • 遍历字符串,记录所有 'a' 的下标到数组 b[1..m]b[1..m],其中 mm'a' 的总数。

    2.2. 不可行情况:

    • 如果 'a' 的数量 mm 和非 'a' 的数量 (nm)(n-m) 都是奇数,则无法对称。
    • 原因:字符串总长 nn 为奇数时,中心位置是 (n+1)/2(n+1)/2
      • mmnmn-m 都是奇数,则 'a' 和非 'a' 都需要占据中心,矛盾。
    • 此时直接输出 -1

    3.3. 计算最小移动距离:

    • 对称位置的下标和为 n+1n+1(例如 11nn22n1n-1)。
    • 将第 ii'a' 与第 (m+1i)(m+1-i)'a' 配对,它们的目标位置和应为 n+1n+1
    • 移动代价为 (n+1)(b[i]+b[m+1i])| (n+1) - (b[i] + b[m+1-i]) |
    • 遍历 i=1m/2i=1 \dots \lfloor m/2 \rfloor,累加代价。

    4.4. 中心 'a' 的处理:

    • 如果 mm 为奇数,则有一个 'a' 需要放在中心位置 (n+1)/2(n+1)/2
    • 代价为 (n+1)/2b[(m+1)/2]| (n+1)/2 - b[(m+1)/2] |

    5.5. 输出结果:

    • 输出总代价 ansans

    复杂度分析:

    • 遍历字符串 O(n)O(n)
    • 计算代价 O(m)O(m)
    • 总体复杂度O(n)O(n),空间复杂度 O(n)O(n)
    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5 + 5;  // 最大字符串长度(2*10^5 +5,适配题目数据规模)
    
    int n;              // 字符串实际长度
    char s[maxn];       // 存储输入的字符串(从索引1开始使用)
    int b[maxn], m;     // b数组:存储字符串中所有'a'的位置;m:'a'的总个数
    
    int main() {
        // 读取字符串(从索引1开始存储),并计算字符串长度n
        scanf("%s", s + 1), n = strlen(s + 1);
    
        // 遍历字符串,收集所有'a'的位置到b数组
        for (int i = 1; i <= n; i++) {
            if (s[i] == 'a') {
                b[++m] = i;  // 第m个'a'的位置是i(m从1开始计数)
            }
        }
    
        // 特殊情况判断:当'a'的数量为奇数,且非'a'的数量也为奇数时,无法对称排列
        // 解释:总长度n = m('a'的数量) + (n-m)(非'a'的数量)
        // 若两者均为奇数,则n为偶数+奇数=奇数,此时对称中心为小数位置,而字符位置是整数,无法完美对称
        if ((m & 1) & (n - m & 1)) {
            return 0 * puts("-1");  // 输出-1并结束程序
        }
    
        long long ans = 0;  // 存储最小移动距离总和(用long long避免溢出)
    
        // 计算对称位置的'a'的移动距离:第i个'a'与第m+1-i个'a'对称
        // 对称中心的位置和为n+1(例如位置1与n对称,2与n-1对称,和均为n+1)
        for (int i = 1; (i << 1) <= m; i++) {  // i << 1 <= m 等价于 i <= m/2
            // 两个对称'a'的目标位置和应为n+1,当前位置和为b[i]+b[m+1-i]
            // 距离差的绝对值即为需要移动的总距离
            ans += abs(n + 1 - b[i] - b[m + 1 - i]);
        }
    
        // 若'a'的数量为奇数,中间的'a'需要移动到整个字符串的中心位置
        if (m & 1) {  // m为奇数(m & 1 结果为1)
            // 字符串中心位置为(n+1)/2(整数除法)
            ans += abs((n + 1 >> 1) - b[(m + 1 >> 1)]);  // m+1>>1 等价于 (m+1)/2,即中间'a'的索引
        }
    
        // 输出计算得到的最小移动距离总和
        return 0 * printf("%lld\n", ans);
    }
        
    
    
    • 1

    信息

    ID
    3173
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者