原题链接:
https://codeforces.com/contest/1675/problem/E
题目大意:给你最多k次操作机会,对字符串某类小写字符进行减小操作,比如可以花费一次操作将所有的'c'改成'b'。求不超过k次操作字典序最小。
解题思路:字典序最小显然应让第一个字符变得最小,如可能变成字母a。如k比较小,不够变成a的话,那么尽可能减小第一个字符。如果k把第一个字符减小之后还有剩余,尝试减小第二个可变字母。
注意,如果第一个字符是f,那么当我们把f变成a时,字符串中所有小于f的如e,d,c也都会变成a。同理,如果如果第一个字符是f,我们先把f变成a,如果第二个字符如果是g,那么只要花费1次操作将g变成f,那么这个g最终也会变成字母a。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int t,n,k;
char v[30],s[200005];
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int i,j;
cin>>t;
s[0]='a';
while(t--)
{
cin>>n>>k>>s+1;
char maxv=s[0];/**< 为了处理方便,把初始最大值设定为a */
for(i=0;i<26;i++)
v[i]=i+'a';/**< v存储每种小写字母变化后的值,初值为自身 */
for(i=1; i<=n&&k>0; i++)
{
if(s[i]>maxv) /**< 可以改变 */
{
if(s[i]-maxv<=k) /**< 机会够就变成a,读者可尝试将ifelse的两个分支整合在一起 */
{
k-=s[i]-maxv;
for(j=s[i]-'a'; j>=0; j--)/**< 如果s[i]能变成a,那么所有比s[i]小的字母也能变成a */
v[j]='a';
}
else/**< 机会k不够尽可能变小 */
{
for(j=s[i]-'a'; j>=s[i]-k-'a'; j--)
v[j]=s[i]-k;
k=0;
}
maxv=s[i];
}
}
for(i=1; i<=n; i++)
cout<<v[s[i]-'a'];
cout<<endl;
}
return 0;
}