2020牛客多校第四场D-Dividing Strings

https://ac.nowcoder.com/acm/contest/5669/D

题意

给出一个由数字构成的字符串,把字符串分成若干不含前导零的子串,求子串间最大差值的最小值

题解

首先可以分成全部长度为1,所以答案一定小于等于9

所以划分只有两种情况,要么全部长度相等,要么最长的和最短的相差1

对于第一种情况,直接枚举约数扫一遍

对于第二种情况,合法的一定是10000...y和9999...x这样类似的,先找到构成10000...y的长度是多少(len),然后分别判断len是否可行和len-1是否可行

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 2e5 + 50;
char s[N];
int n;
int ans;
int cmx[N], cmn[N], cnow[N];
bool cmp(int a[], int b[], int len) {
    for (int i = 1; i <= len; i++) if (a[i] != b[i]) return a[i] > b[i];
    return 0;
}
void copy(int a[], int b[], int len) {
    for (int i = 1; i <= len; i++) a[i] = b[i];
}
void check(int len) {
    for (int j = 1; j <= len; j++) cmn[j] = 9, cmx[j] = 0;
    for (int j = 1; j <= n; j++) {
        if (j % len == 1 && s[j] == '0') return;
        cnow[(j-1)%len+1] = s[j] - '0';
        if (j % len == 0) {
            if (cmp(cnow, cmx, len)) copy(cmx, cnow, len);
            if (cmp(cmn, cnow, len)) copy(cmn, cnow, len); 
        }
    }
    int mni = 9;
    for (int j = len; j >= 1; j--) {
        int t = cmx[j] - cmn[j];
        if (t < 0) cmx[j - 1]--, t += 10;
        if (j == len) mni = t;
        else if (t > 0) return;
    }
    ans = min(ans, mni);
}
int find() {
    for (int now = 1; now <= n; now++) {
        if (s[now] == '1') {
            int l = now;
            while (now < n && s[now + 1] == '0') now++;
            if (now < n && s[now + 1] != '9') now++;
            return now - l + 1;
        }
    }
    return -1;
}
int calc(int len) {
    int n1 = -1, n9 = 10;
    for (int now = 1; now <= n; now++) {
        int l = now;
        if (s[now] == '1') {
            while (now < n && s[now + 1] == '0') now++;
            if (now < n && now - l + 1 < len && s[now + 1] != '9') now++;
            if (now - l + 1 != len) return 9;
            n1 = max(n1, s[now] - '0');
        }
        else {
            now--;
            while (now < n && s[now + 1] == '9' && now - l + 1 < len - 1) now++;
            if (now < n && now - l + 1 < len - 1) now++;
            if (now - l + 1 != len - 1) return 9;
            n9 = min(n9, s[now] - '0');
        }
    }
    if (n9 == 10 || n1 == -1) return 9;
    return n1 + 10 - n9;
}
int main() {
    int t; scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        scanf("%s", s + 1);
        int mxi = 0, mni = 1e9;
        for (int i = 1; i <= n; i++) {
            mxi = max(mxi, s[i] - '0');
            mni = min(mni, s[i] - '0');
        }
        ans = mxi - mni;
        for (int i = 2; i < n; i++) {
            if (n % i == 0) check(i);
        }
        int len = find();
        if (len > 1) ans = min(ans, calc(len));
        if (len > 2) ans = min(ans, calc(len - 1));
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/artoriax/p/13590063.html