zoukankan      html  css  js  c++  java
  • Codeforces Round #650 (Div. 3) F1经典离散化DP

    比赛链接:Here

    1367A. Short Substrings

    Description

    一个字符串 abac,然后把所有长度为2的子串加起来变成新串,abbaac,由 ab ba ac组成。现在给出新串,找出原串。


    直接模拟即可

    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            string s; cin >> s;
            cout << s[0];
            for (int i = 1; i < s.size(); i += 2) cout << s[i];
            cout << "
    ";
        }
    }
    

    1367B. Even Array

    Description

    给定一个数组。有一种操作,可以交换任意两个数的位置。要求的数组奇偶交替出现。最少需要多少次操作。


    先统计一遍都多少个奇数不在位置上,和多少个偶数不在位置上。如果不相等,那么无解。反之,把他们放到对应的位置就好了。

    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            int n; cin >> n;
            vector<int> a(n);
            for (int &x : a) cin >> x;
            int cnt0 = 0, cnt1 = 0, ans = 0;
            for (int i = 0; i < n; ++i) {
                cnt0 += a[i] % 2;
                cnt1 += i % 2;
                if (i % 2 == 1 && a[i] % 2 == 0) ans += 1;
            }
            if (cnt0 != cnt1) cout << "-1
    ";
            else cout << ans << "
    ";
        }
    }
    

    1367C. Social Distance

    Description

    给定一个01串。需要保证两个相邻的1之间的距离大于k。求原串在不违背题意的情况下,还能插入多少个1。


    这个需要分情况考虑。左边连续的0单独计数。右边连续的0单独计数。中间出现的连续的0单独计数。

    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            int n, k; string s;
            cin >> n >> k >> s;
            int sum = 0, cnt = 0, pre = 0;
            k += 1;
            bool f = false;
            for (int i = 0; i < n; ++i) {
                if (s[i] == '0') cnt += 1;
                else {
                    f = true;
                    if (pre == 0) sum += max(0, cnt / k);
                    else sum += max(0, (cnt - k + 1) / k);
                    pre = 1, cnt = 0;
                }
            }
            sum += max(0, cnt / k);
            if (!f) sum = max(1 + max(0, (n - 1) / k), sum);
            cout << sum << "
    ";
        }
    }
    
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            int n, k; string s;
            cin >> n >> k >> s;
            int sum = 0, cnt1 = 0, cnt0 = 0;
            for (int i = 0; i < n; ++i) {
                if (s[i] == '1') {
                    cnt1 += 1;
                    if (cnt1 == 1)
                        sum += cnt0 / (k + 1);
                    else {
                        sum += (cnt0 - k) / (k + 1);
                        cnt1 = 1;
                    }
                    cnt0 = 0;
                }
                if (s[i] == '0') cnt0 += 1;
                if (i == n - 1 && s[i] == '0' && cnt1 != 0)
                    sum += cnt0 / (k + 1);
            }
            if (cnt1 == 0) sum += (cnt0 + k) / (k + 1);
            cout << sum << "
    ";
        }
    }
    

    1367D. Task On The Board

    Description

    给定s串,删除一些字符,重新组合,得到t串。根据t串,可以计算一个b数组。$b_i = sum(|j-i|)$ if $t_j > t_i$,也就是所有比i位置大的字符的位置差的和。现在给定s和b数组,求t串。


    首先肯定是找 (b) 数组为 (0) 的位置。因为(0) ,就表示,没有比他更大的字符了。然后这些位置填上了字符之后,对于非 (0) 的位置,他们都是有贡献的。把这些贡献从 (b) 数组中减掉,就又会尝试新的 (0) 的位置。就循环模拟这个过程就好了。

    const int N = 50;
    int b[N];
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            string s; int m;
            cin >> s >> m;
            for (int i = 0; i < m; ++i) cin >> b[i];
            int cnt[30] = {};
            for (auto c : s) cnt[c - 'a'] += 1;
            int r = m, l = 25;
            string t(m, '?');
            while (r) {
                int c = 0;
                for (int i = 0; i < m; ++i)
                    if (!b[i]) c += 1;
                while (cnt[l] < c) l -= 1;
                for (int i = 0; i < m; ++i) {
                    if (!b[i]) {
                        t[i] = 'a' + l;
                        b[i] -= 1;
                        r -= 1;
                    }
                }
                for (int i = 0; i < m; ++i) {
                    if (t[i] == 'a' + l)
                        for (int j = 0; j < m; ++j)
                            if (b[j] > 0) b[j] -= abs(i - j);
                }
                l -= 1;
            }
            cout << t << "
    ";
        }
    }
    

    1367E. Necklace Assembly

    Description

    给定一堆字符。然后选出len个,围成一圈。且以k为循环节。即每转动k次,这个圈看上去是一模一样的。给定k。求最大的len。


    (K) 为循环节。那么以 (K) 的因子 (K) 为循环节都可以。所以先枚举 (K) 的所有因子。然后对于每个循环节 (K) ,如果只由 (K) 个元素组成。那显然是可以的。但是要要枚举 (2*k) ,可不可以,(3*k) 可不可以,直到找到一个最大的 (n*k) 可行。那么对于循环节 (k) 。最大长度就是 (n*k) 。对所有枚举到的取 (max) 就好了。

    int check(int k, int cnt[]) {
        int tmp = k;
        for (int j = 2;; j += 1) {
            int tt = 0;
            for (int i = 0; i < 26; ++i) tt += cnt[i] / j;
            if (tt >= k) tmp = j * k;
            else return tmp;
        }
    }
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            int cnt[100] = {};
            string s;
            int n, m;
            cin >> n >> m >> s;
            for (int i = 0; i < n; ++i) cnt[s[i] - 'a'] += 1;
            sort(cnt, cnt + 100);
            reverse(cnt, cnt + 100);
            int ans = 1;
            for (int i = 1; i <= m && i <= n; ++i) {
                if (m % i == 0)
                    ans = max(ans, check(i, cnt));
            }
            cout << ans << "
    ";
        }
    }
    

    1367F1. Flying Sort (Easy Version)

    Description

    一个数组,一次操作可以选择一个数,放到数组开头,或者放到末尾。问最少多少次操作可以使得数组有序。Easy版中所有元素各不相同。且数组长度 $< 3000$。


    超级经典 DP + 离散化处理,⭐一下

    考虑求不需要动的元素。先对 (a) 数组离散化,变成值域 (1sim n) 的数组。然后不需要动的元素是差值为 (1) 的连续上升子序列。DP 求这个最大长度就好了。其他的数都是要移动的。并且要移动一个数。至多只移动一次就好了。所以求出最长子序列长度,再用 (n) 减去就是答案了。

    const int N = 1e6 + 10;
    int a[N], b[N], f[N];
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            int n; cin >> n;
            for (int i = 0; i < n; ++i) cin >> b[i], a[i] = b[i];
            sort(b, b + n);
            for (int i = 0; i <= n ; ++i) f[i] = 0;
            for (int i = 0; i < n; ++i) a[i] = lower_bound(b, b + n, a[i]) - b + 1;
            int ans = 0;
            for (int i = 0; i < n; ++i) {
                f[a[i]] = f[a[i] - 1] + 1;
                ans = max(ans, f[a[i]]);
            }
            cout << n - ans << "
    ";
        }
    }
    

    1367F2. Flying Sort (Hard Version)

    AC参考代码

    const int N = 2e5 + 10;
    int a[N], p[N];
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int _; for (cin >> _; _--;) {
            int n; cin >> n;
            for (int i = 0; i < n; ++i) cin >> a[i];
            iota(p, p + n, 0);
            sort(p, p + n, [&](int i, int j) {return a[i] < a[j] || a[i] == a[j] && i < j;});
            int ans = 0;
            for (int l = 0, r; l < n; l = r) {
                for (r = l + 1; r < n && p[r] > p[r - 1]; ++r);
                int cnt = r - l;
                if (l)
                    for (int i = l - 1; i >= 0 && a[p[i]] == a[p[l - 1]]; i--)
                        if (p[i] < p[l]) cnt += 1;
                if (r < n)
                    for (int i = r; i < n && a[p[i]] == a[p[r]]; ++i)
                        if (p[i] > p[r - 1]) ++ cnt;
                ans = max(ans, cnt);
            }
            for (int l = 0, m, r; l < n; l = m) {
                for (m = l; m < n && a[p[m]] == a[p[l]]; ++m);
                if (m == n) break;
                for (r = m; r < n && a[p[r]] == a[p[m]]; ++r);
                for (int i = l, j = m; i < m; ++i) {
                    while (j < r && p[j] < p[i]) ++j;
                    ans = max(ans, i + 1 - l + r - j);
                }
            }
            cout << n - ans << "
    ";
        }
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    寒假短期学习计划
    PAT 1001 A+B 解题报告
    JavaScript 原型链、继承
    JavaScript 数据扁平化处理
    每周一篇React: 高阶 hoc_component 使用
    每天一道算法题: day1 翻转图像
    项目中下载加权,你是怎么做的,欢迎评论。
    前端封装验证码方法,封装验证码类
    文件下载之后默认不打开实现方式
    文件下载之后默认不打开实现方式
  • 原文地址:https://www.cnblogs.com/RioTian/p/15149661.html
Copyright © 2011-2022 走看看