地址: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; } }