细节还是挺多的
首先找一个使得价值最小的数,注意这个数可能有很多,我们都要把它们存下来,然后尝试更改,注意字典序问题,从后到前还是从前到后更改。
其中有贪心思想:设最后更改为x,则按照x+1,x-1,x+2,x-2...顺序更改。
注意char数组比较字典序不能直接用小于号来比较
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=500005;
typedef long long ll;
int p,n,k,maxn,pos[N];
ll maxx=1e18;
int read(){
int num=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
num=num*10+c-'0';
c=getchar();
}
return num*f;
}
char s[N],anss[N],ss[N];
int xx;
int b[N][10],cnt[10],tot[10];
ll solve(int x,int rest){
int res=0;
int d=1;
while(rest){
if(x+d>9){
d=-d;
continue;
}
if(x+d<0){
d=-(d-1);
continue;
}
if(abs(d)>9) break;
if(rest<=cnt[x+d]){
tot[x+d]+=rest;
res+=abs(d)*rest;
rest=0;
}
if(rest>cnt[x+d]){
rest-=cnt[x+d];
tot[x+d]+=cnt[x+d];
res+=abs(d)*cnt[x+d];
}
if(d<0) d=-(d-1);
else d=-d;
}
return res;
}
bool cmp(char *a,char *b){
for(int i=0;i<n;i++){
if(a[i]==b[i]) continue;
else if(a[i]>b[i]) return 1;
else return 0;
}
return 1;
}
int main(){
n=read(); k=read();
anss[1]='-';
scanf("%s",s+1);
for(int i=1;i<=n;i++){
cnt[s[i]-'0']++;
maxn=max(maxn,cnt[s[i]-'0']);
}
if(maxn>=k){
printf("0
");
printf("%s",s+1);
return 0;
}
for(int i=0;i<=9;i++){
if(!cnt[i]) continue;
memset(tot,0,sizeof(tot));
ll tmp=solve(i,k-cnt[i]);
if(maxx>tmp){
maxx=tmp;
xx=1;
pos[xx]=i;
for(int j=0;j<=9;j++) b[xx][j]=tot[j];
}
else if(maxx==tmp){
maxx=tmp;
pos[++xx]=i;
for(int j=0;j<=9;j++) b[xx][j]=tot[j];
}
}
for(int k=1;k<=xx;k++){
for(int i=1;i<=n;i++) ss[i]=s[i];
for(int i=0;i<=9;i++){
if(i<pos[k]){
if(b[k][i]){
for(int j=n;j>=1;j--){
if(s[j]-'0'==i){
ss[j]=(char)(pos[k]+'0');
b[k][i]--;
}
if(b[k][i]==0) break;
}
}
}
else{
if(b[k][i]){
for(int j=1;j<=n;j++){
if(s[j]-'0'==i){
ss[j]=(char)(pos[k]+'0');
b[k][i]--;
}
if(b[k][i]==0) break;
}
}
}
}
if(anss[1]=='-') for(int p=1;p<=n;p++) anss[p]=ss[p];
if(cmp(anss,ss)) for(int p=1;p<=n;p++) anss[p]=ss[p];
}
printf("%lld
",maxx);
cout<<anss+1;
return 0;
}