【CodeForces】CF1385D a-Good String

题目地址:

https://www.luogu.com.cn/problem/CF1385D

题目描述:
定义:字符串s为一个c-好串(c 为一个字符)时,必须满足:

  1. ∣ s ∣ = 1 |s| = 1 s=1 s = c s = c s=c
  2. ∣ s ∣ > 1 |s| > 1 s>1, s s s 的左半部分为全为 c c c,右半部分为一个 (c+1)-好串或者 s s s 的右半部分为全为 c c c,左半部分为一个 (c+1)-好串

其中 ∣ s ∣ |s| s 代表 字符串 s s s 的长度。
举个例子:当 s = “ c d b b a a a a " s=“cdbbaaaa" s=cdbbaaaa"时, s s s 是一个 a-好串
现在,给你一个字符串 s s s ( ∣ s ∣ = 2 k |s| = 2^k s=2k ),问最少替换多少个字符,使其为一个 a-好串

题目描述:
You are given a string s [ 1 … n ] s[1 \dots n] s[1n] consisting of lowercase Latin letters. It is guaranteed that n = 2 k n = 2^k n=2k for some integer k ≥ 0 k \ge 0 k0 .

The string s [ 1 … n ] s[1 \dots n] s[1n] is called c c c -good if at least one of the following three conditions is satisfied:

  • The length of s s s is 1 1 1 , and it consists of the character c c c (i.e. s 1 = c s_1=c s1=c );
  • The length of s s s is greater than 1 1 1 , the first half of the string consists of only the character c c c (i.e. s 1 = s 2 = ⋯ = s n 2 = c s_1=s_2=\dots=s_{\frac{n}{2}}=c s1=s2==s2n=c ) and the second half of the string (i.e. the string s n 2 + 1 s n 2 + 2 … s n s_{\frac{n}{2} + 1}s_{\frac{n}{2} + 2} \dots s_n s2n+1s2n+2sn ) is a ( c + 1 ) (c+1) (c+1) -good string;
  • The length of s s s is greater than 1 1 1 , the second half of the string consists of only the character c c c (i.e. s n 2 + 1 = s n 2 + 2 = ⋯ = s n = c s_{\frac{n}{2} + 1}=s_{\frac{n}{2} + 2}=\dots=s_n=c s2n+1=s2n+2==sn=c ) and the first half of the string (i.e. the string s 1 s 2 … s n 2 s_1s_2 \dots s_{\frac{n}{2}} s1s2s2n ) is a ( c + 1 ) (c+1) (c+1) -good string.

For example: “aabc” is ‘a’-good, “ffgheeee” is ‘e’-good.

In one move, you can choose one index i i i from 1 1 1 to n n n and replace s i s_i si with any lowercase Latin letter (any character from ‘a’ to ‘z’).

Your task is to find the minimum number of moves required to obtain an ‘a’-good string from s s s (i.e. c c c -good string for c = c= c= ‘a’). It is guaranteed that the answer always exists.

You have to answer t t t independent test cases.

Another example of an ‘a’-good string is as follows. Consider the string s = s = s= “cdbbaaaa”. It is an ‘a’-good string, because:

  • the second half of the string (“aaaa”) consists of only the character ‘a’;
  • the first half of the string (“cdbb”) is ‘b’-good string, because:
    • the second half of the string (“bb”) consists of only the character ‘b’;
    • the first half of the string (“cd”) is ‘c’-good string, because:
      • the first half of the string (“c”) consists of only the character ‘c’;
      • the second half of the string (“d”) is ‘d’-good string.

输入格式:
The first line of the input contains one integer t t t ( 1 ≤ t ≤ 2 ⋅ 1 0 4 1 \le t \le 2 \cdot 10^4 1t2104 ) — the number of test cases. Then t t t test cases follow.

The first line of the test case contains one integer n n n ( 1 ≤ n ≤ 131   072 1 \le n \le 131~072 1n131 072 ) — the length of s s s . It is guaranteed that n = 2 k n = 2^k n=2k for some integer k ≥ 0 k \ge 0 k0 . The second line of the test case contains the string s s s consisting of n n n lowercase Latin letters.

It is guaranteed that the sum of n n n does not exceed 2 ⋅ 1 0 5 2\cdot 10^5 2105 ( ∑ n ≤ 2 ⋅ 1 0 5 \sum n \le 2 \cdot 10^5 n2105 ).

输出格式:
For each test case, print the answer — the minimum number of moves required to obtain an ‘a’-good string from s s s (i.e. c c c -good string with c = c = c= ‘a’). It is guaranteed that the answer exists.

思路是分治。代码如下:

#include <iostream>
using namespace std;

const int N = 2e5 + 10;
int n;
char s[N];

int dfs(int l, int r, char x) {
  if (l == r) return x == s[l] ? 0 : 1;
  int mid = l + (r - l >> 1);
  int y1 = 0, y2 = 0;
  for (int i = l; i <= mid; i++)
    if (s[i] != x) y1++;
  for (int i = mid + 1; i <= r; i++)
    if (s[i] != x) y2++;

  return min(y1 + dfs(mid + 1, r, x + 1), y2 + dfs(l, mid, x + 1));
}

int main() {
  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d%s", &n, s + 1);
    printf("%d\n", dfs(1, n, 'a'));
  }
}

每组数据时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间 O ( log ⁡ n ) O(\log n) O(logn)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值