2020牛客暑期多校训练营(第四场)D-Dividing Strings 贪心乱搞
题意
给一个长度为\(n\)的数字串\(s\),现在让你将这个数字串分成若干个小段,每段的值即为它代表的数字,使最大值和最小值的差值最小。
分析
Code
#include<bits/stdc++.h>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int inf=1e9;
int T,n;
char s[N];
int sum[N];
int cal(string a,string b){
int l=b.size();
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int cnt=0;
for(int i=0;i<l;i++){
if(a[i]<b[i]){
a[i]+=10;
a[i+1]--;
}
a[i]-=b[i]-'0';
}
reverse(a.begin(),a.end());
for(char x:a){
x-='0';
cnt=cnt*10+x;
if(cnt>9) return inf;
}
return cnt;
}
int gao(int x){
for(int i=1;i<=n;i++){
if(i%x==1&&s[i]=='0') return inf;
}
string a,b,t;
rep(i,1,n){
t.pb(s[i]);
if(i%x==0){
if(a.empty()||a<t) a=t;
if(b.empty()||b>t) b=t;
t="";
}
}
return cal(a,b);
}
int sol(int x){
int c1=-1,c2=10;
for(int i=1;i<=n;){
if(s[i]=='1'){
if(i+x<=n&&sum[i+x-1]-sum[i-1]==1){
c1=max(c1,s[i+x]-'0');
i+=x+1;
}else return 9;
}else{
if(i+x-1<=n&&sum[i+x-2]-sum[i-1]==(i+x-2-i+1)*9){
c2=min(c2,s[i+x-1]-'0');
i+=x;
}else return 9;
}
}
if(c1==-1||c2==10) return 9;
return c1+10-c2;
}
int main(){
//ios::sync_with_stdio(false);
// freopen("data.in","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d",&n);
scanf("%s",s+1);
int mn=1,mx=1;
rep(i,1,n){
if(s[i]>s[mx]) mx=i;
if(s[i]<s[mn]) mn=i;
sum[i]=sum[i-1]+s[i]-'0';
}
int ans=s[mx]-s[mn];
for(int i=1;i<=n;i++) if(n%i==0&&n/i>=2){
ans=min(ans,gao(i));
}
for(int i=1;i<=n-1;i++){
ans=min(ans,sol(i));
}
printf("%d\n",ans);
}
return 0;
}