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