SDUT 2021 Autumn Team Contest 9th(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDUT 2021 Autumn Team Contest 9th(补题)相关的知识,希望对你有一定的参考价值。

H - Hamming Distance


题意:

给定两个字符串 a a a b b b,让你输出一个字典序最小的字符串与输入的字符串的汉明距离相同。两个字符串的汉明距离指两个字符串的不同的字符数量。

思路:

要求字典序最小,那么越前面的字母最好都放 a a a,如果放不了 a a a,那就放字典序小的字母。贪心的思路从前往后,放越小的字母越好。此时如果两个字符串相同位置的字符一样那么,那么直接放最小字母a即可,因为不影响汉明距离。如果两个字符不相同,那么此时放下的最小字母如果与其中一个字母相同,就以a串对应位置的字母相同,相当于,a串此刻不用变换,而b串需要变换,此时a串和b串对于答案串的汉明距离就不一样了,现在放下什么字母就需要考虑,后面能够通过放一些特殊的字母来使得a串汉明距离+1,而b串不变,而这一操作对于后面的字母一定是指后面对应位置不同的字母来说的。
所以,具体操作,就是先统计一下整个a串和b串对应位置不同字母的数量,再求一遍后缀和,记录的是当前位置开始一直到最后有多少个对应位置的不同的字母,而每次贪心放下字母时,都要记录记录一个相对汉明距离 d i s t a n c e distance distance>0,代表此时a串还需要放 d i s t a n c e distance distance个不同字母,b串放 d i s t a n c e distance distance个相同字母字母,才能保证最后 d i s t a n c e distance distance = 0 =0 =0, < 0 <0 <0同理。在每次贪心放字母时,要考虑放下当前这个字母,能否通过后面对应位置的不同字母来使distance最后为0

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
string a, b;
int f[N];
int dis = 0;
bool check(int dex, char x) {
    int now = dis;
    if (x != a[dex]) now++;
    if (x != b[dex]) now--;
    return abs(now) <= f[dex + 1];
}
int main() {
    int T, idx = 1;
    cin >> T;
    while (T--) {
        cin >> a >> b;
        int len = a.size();
        f[len] = 0;
        memset(f, 0, sizeof(f));

        for (int i = len - 1; i >= 0; i--) {
            f[i] += a[i] != b[i];
        }
        for (int i = len - 1; i >= 0; i--) {
            f[i] = f[i + 1] + f[i];
        }
        printf("Case %d: ", idx++);
        dis = 0;
        for (int i = 0; i < len; i++) {
            for (char j = 'a'; j <= 'z'; j++) {
                if (!check(i, j)) continue;
                cout << j;
                if (j != a[i]) dis++;
                if (j != b[i]) dis--;
                break;
            }
        }
        cout << '\\n';
    }
    return 0;
}

A - Array Merge

学习的一位大佬的博客,在下面放上链接

链接: link.

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
ll a[N], b[N];
ll x[N], y[N];
int n, m;
ll res;
ll la[N], lb[N];
ll blocka[N], blockb[N];
ll topa, topb;
void input() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        ll dex;
        scanf("%lld", &dex);
        x[i] = a[i] = dex;
    }
    for (int i = 1; i <= m; i++) {
        ll dex;
        scanf("%lld", &dex);
        y[i] = b[i] = dex;
    }
}

void merge() {
    for (int i = 1; i <= n; i++) {
        la[i] = 1;
    }
    int now = n;
    bool flag = 1;
    while (flag) {
        flag = 0;
        now = n;
        for (int i = n - 1; i >= 1; i--) {
            if (a[i]) {
                ll l = 1ll * a[now] * la[i];
                ll r = 1ll * a[i] * la[now];
                if (l > r) {
                    a[now] += a[i], a[i] = 0;
                    la[now] += la[i], la[i] = 0;
                    flag = 1;
                } else {
                    now = i;
                }
            }
        }
    }

    for (int i = 1; i <= m; i++) {
        lb[i] = 1;
    }
    now = m;
    flag = 1;
    while (flag) {
        flag = 0;
        now = m;
        for (int i = m - 1; i >= 1; i--) {
            if (b[i]) {
                ll l = 1ll * b[now] * lb[i];
                ll r = 1ll * b[i] * lb[now];
                if (l > r) {
                    b[now] += b[i], b[i] = 0;
                    lb[now] += lb[i], lb[i] = 0;
                    flag = 1;
                } else
                    now = i;
            }
        }
    }
}

void presolve() {
    topa = 0, topb = 0;
    int now = 0;
    for (int i = 1; i <= n; i++) {
        now++;
        if (a[i]) {
            blocka[++topa] = now;
            now = 0;
        }
    }
    now = 0;
    for (int i = 1; i <= m; i++) {
        now++;
        if (b[i]) {
            blockb[++topb] = now;
            now = 0;
        }
    }
    for (int i = 1; i <= n; i++) {
        a[i] = x[i];
    }
    for (int i = 1; i <= m; i++) {
        b[i] = y[i];
    }
    for (int i = 1; i <= n; i++) {
        x[i] += x[i - 1];
    }
    for (int i = 1; i <= m; i++) {
        y[i] += y[i - 1];
    }
}

void solve() {
    int l, r, i, j;
    i = j = l = r = 1;
    res = 0;
    int now = 1;
    while (l <= topa || r <= topb) {
        ll sum1, sum2;
        sum1 = 1ll * (x[i + blocka[l] - 1] - x[i - 1]) * blockb[r];
        sum2 = 1ll * (y[j + blockb[r] - 1] - y[j - 1]) * blocka[l];
        if (r > topb) {
            for (int u = 1; u <= blocka[l]; u++) {
                res += 1ll * a[i++] * now++;
            }
            l++;
        } else if (l > topa) {
            for (int u = 1; u <= blockb[r]; u++) {
                res += 1ll * b[j++] * now++;
            }
            r++;
        } else {
            if (sum1 > sum2) {
                for (int u = 1; u <= blocka[l]; u++) {
                    res += 1ll * a[i++] * now++;
                }
                l++;
            } else {
                for (int u = 1; u <= blockb[r]; u++) {
                    res += 1ll * b[j++] * now++;
                }
                r++;
            }
        }
    }
}
int main() {
    int T, idx = 1;
    scanf("%d", &T);
    while (T--) {
        res = 0;
        input();
        merge();
        presolve();
        solve();
        printf("Case %d: %lld\\n", idx++, res);
    }
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于SDUT 2021 Autumn Team Contest 9th(补题)的主要内容,如果未能解决你的问题,请参考以下文章

SDUT 2021 summer team contest 1st(for 20)(补题)

SDUT 2022 Winter Team Contest - 1

SDUT 2022 Winter Team Contest - 1

SDUT 2022 Winter Team Contest - 1

SDUT 2021 Spring Individual Contest(for 20) - 18(补题)

SDUT 2021 Summer Individual Contest - 2(for 20)(补题)