Codeforces Round #656 (Div. 3)D a-Good String(递归分治)

地址:https://codeforces.com/contest/1385/problem/D

题意:

给定一个字符串s,长度为2的幂次
规定一个字符串叫做c-good,如果它满足以下任意一个条件:

1:字符串长度为1,左半边都是c,右半边是c+1--good

2:字符串长度>1,左半边为c--good,右半边为c+1--good

3:字符串长度>1,左半边为c+1--good,右半边为c--good

求修改最少的字符使得s变成'a'-good

解析:

涉及到左,右半边,可以考虑用递归分治做。

题目规定变成'a'--good,那么就从'a'入手,算出左半边全变成'a'用的次数和右半边用的次数,

左半边变的话,递归进入右半边a+1

右半边变的话,递归进入左半边a+1

取个最小值即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<map>
#include<map>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+7;
int l[maxn],r[maxn];
int a[maxn];
int b[8*maxn];
int vis[maxn];
ll c[maxn],d[maxn];
int pos[maxn];
const int maxn2=2e3+10;
char mp[maxn2][maxn2];
int dp[maxn2][maxn2];
string s;
int n;
int len;
int ac(int l,int r,char ch)
{
    if(l==r)
        return s[l]!=ch;    //s[l]==ch,返回0,否则返回1,即修改
    int c1=0,c2=0;
    int md=(l+r)/2;
    for(int i=l;i<=md;i++)
        if(s[i]!=ch)
            c1++;
    for(int i=md+1;i<=r;i++)
        if(s[i]!=ch)
            c2++;
    c1+=ac(md+1,r,ch+1);
    c2+=ac(l,md,ch+1);
    return min(c1,c2);
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        cin>>s;
        len=s.length();
        cout<<ac(0,len-1,'a')<<endl;
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/13471308.html