CF118C Fancy Number(模擬)

細節還是挺多的

首先找一個使得價值最小的數,注意這個數可能有很多,我們都要把它們存下來,然後嘗試更改,注意字典序問題,從後到前還是從前到後更改。

其中有貪心思想:設最後更改爲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\n");
		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\n",maxx);
	cout<<anss+1;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章