CF 1555 D. Say No to Palindromes

D. Say No to Palindromes

题目大意

给定一个仅由\(a,b,c\)组成的串\(s\),有\(m\)组询问,每次询问给出\(l,r\),问将子串\(s[l..r]\)变成好串所需要的最小操作次数。

若一个串不包含长度大于\(1\)的回文串,则这是个好串。

你能进行的一个操作是,将某个字母替换成\(a,b,c\)中的一个。

解题思预处理路

注意到串的组成字母只有\(a,b,c\),前三个字母必须俩俩不同,那么只有\(3!=6\)种情况,然后前三个字母确定了,整个串的字母也确定了。

于是枚举六种可能的串的样子,分别计算操作次数,取最小值即可。

前缀和预处理。

神奇的代码
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 2e5 + 8;

int sum[6][N];

int n, m;

string s;

string cmp;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    cin >> n >> m >> s;
    cmp = "abc";
    int p = 0;
    do{
        int cur = 0;
        for(int i = 0; i < n; ++ i){
            sum[p][i + 1] = (s[i] != cmp[cur]);
            cur ++;
            if (cur == 3)
                cur = 0;
        }
        ++ p;
    }while(next_permutation(cmp.begin(), cmp.end()));
    for(int i = 0; i < 6; ++ i)
        for(int j = 2; j <= n; ++ j)
            sum[i][j] += sum[i][j - 1];
    for(int i = 1; i <= m; ++ i){
        int l, r;
        cin >> l >> r;
        int ans = 1e9 + 7;
        for(int i = 0; i < 6; ++ i)
            ans = min(ans, sum[i][r] - sum[i][l - 1]);
        cout << ans << '\n';
    }
    return 0;
}


posted @ 2021-09-08 10:38  ~Lanly~  阅读(75)  评论(0编辑  收藏  举报