zoukankan      html  css  js  c++  java
  • Codeforces Round #743 (Div. 2) 题解

    旅行传送门

    A. Countdown

    题意:给你一个 \(n\) 位的字符串。每位均为一个从 \(0\)\(9\) 的整数(即整个字符串表示一个从 \(0\)\(10^{n-1}\) 的整数)。你可以执行以下操作之一任意次:

    • 将字符串表示的数字减 \(1\)
    • 交换任意两位数字

    求使整个字符串转变为 \(0\) 字符串所需的最少操作数。

    题目分析:最优解显然是将其它位上的数字交换至个位上再减为 \(0\) ,除了原本就在个位上的数之外,其余各数的花费均为: \(s[i]\) (变 \(0\) 费用) + \(1\) (交换费用)。

    AC代码

    #include <bits/stdc++.h>
    #define rep(i, x, y) for (register int i = (x); i <= (y); i++)
    #define down(i, x, y) for (register int i = (x); i >= (y); i--)
    #define IOS                      \
        ios::sync_with_stdio(false); \
        cin.tie(nullptr);            \
        cout.tie(nullptr);
    using ll = long long;
    using namespace std;
    
    ll solve()
    {
        int n;
        string s;
        cin >> n >> s;
        ll res = 0;
        for (auto x : s)
            if (x - '0')
                res += x - '0' + 1;
        if (s[n - 1] - '0')
            --res;
        return res;
    }
    
    int main(int argc, char const *argv[])
    {
        IOS;
        int T;
        cin >> T;
        while (T--)
            cout << solve() << endl;
        return 0;
    }
    

    B. Swaps

    题意:给你两个长度均为 \(n\) 的序列 \(a\)\(b\) 。序列 \(a\) 仅包含从 \(1\)\(2n\) 的每个奇数,序列 \(b\) 仅包含从 \(1\)\(2n\) 的每个偶数。

    你可以对这两个序列执行以下操作:

    • 选择两序列之一
    • 选择从 \(1\)\(n−1\) 的一个索引 \(i\)
    • 交换所选序列的第 \(i\) 个和第 \((i+1)\) 个元素

    计算使序列 \(a\) 的字典序小于序列 \(b\) 所需的最小操作数。

    题目分析:要使得字典序最小,显然有 \(a[1] < b[1]\) 。考虑暴力的做法,枚举每个 \(a_i\) 为首时,将符合条件的 \(b_i\) 挪至列首的总费用,时间复杂度 \(O(n^2)\)

    如何优化?假设现在 \(a[1] = x\) ,那符合条件的 \(b_i\) 必为 \(x+1\)\(x+3\)\(x+5 \cdots 2n-2\)\(2n\) 。因此我们可以用 \(pair<int,int>\) 记录下每个元素的初始位置和元素大小,按值排序后用后缀和的思想预先处理出 \(b\) 序列中 \([x+1,2n]\) 挪至列首费用的最小值后再进行计算,时间复杂度降至 \(O(n)\)

    AC代码

    #include <bits/stdc++.h>
    #define rep(i, x, y) for (register int i = (x); i <= (y); i++)
    #define down(i, x, y) for (register int i = (x); i >= (y); i--)
    #define pii std::pair<int, int>
    #define mp std::make_pair
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5 + 5;
    
    char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
    #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    inline int read()
    {
        int x = 0, f = 1;
        char ch = getchar();
        while (!isdigit(ch))
        {
            if (ch == '-')
                f = -1;
            ch = getchar();
        }
        while (isdigit(ch))
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    
    int solve()
    {
        int n = read();
        std::vector<pii> a(n + 1), b(n + 1);
        std::vector<int> mn(n + 1);
        rep(i, 1, n) a[i].first = read(), a[i].second = i;
        rep(i, 1, n) b[i].first = read(), b[i].second = i;
        std::sort(a.begin() + 1, a.begin() + n + 1);
        std::sort(b.begin() + 1, b.begin() + n + 1);
        mn[n] = b[n].second;
        down(i, n - 1, 1) mn[i] = std::min(mn[i + 1], b[i].second);
        int res = inf;
        rep(i, 1, n) res = std::min(res, a[i].second + mn[i] - 2);
        return res;
    }
    
    int main(int argc, char const *argv[])
    {
        int T = read();
        while (T--)
            printf("%d\n", solve());
        return 0;
    }
    

    C. Book

    题意:给你一本有 \(n\) 章的书。每章都有一定数量的前置章节,需要理解所有的前置章节后才能理解本章的内容。现在你将从头到尾反复阅读本书,直到你理解整本书。问你在阅读多少遍后才能啃完这本书,或读懂这本书对你来说为时尚早。

    题目分析:画下样例不难发现是拓扑排序。套个拓扑排序的板子,当某章节入度为 \(0\) 入队时,若其编号大于前置章节,则该章节这一轮阅读就能读到,否则要等到下一轮,我们可以用优先队列维护当前可读章节的阅读顺序。

    AC代码

    #include <bits/stdc++.h>
    #define rep(i, x, y) for (register int i = (x); i <= (y); i++)
    #define down(i, x, y) for (register int i = (x); i >= (y); i--)
    #define pii std::pair<int, int>
    #define mp std::make_pair
    
    char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
    #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    inline int read()
    {
        int x = 0, f = 1;
        char ch = getchar();
        while (!isdigit(ch))
        {
            if (ch == '-')
                f = -1;
            ch = getchar();
        }
        while (isdigit(ch))
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    
    int solve()
    {
        int n = read();
        std::vector<int> in(n + 1);
        std::vector<int> e[n + 1];
        std::priority_queue<pii, std::vector<pii>, std::greater<pii>> q;
        rep(i, 1, n)
        {
            int k = in[i] = read();
            if (!in[i])
                q.push(mp(1, i));
            rep(j, 1, k) e[read()].push_back(i);
        }
        int res, cnt = 0;
        while (!q.empty())
        {
            pii cur = q.top();
            q.pop();
            res = cur.first;
            ++cnt;
            for (auto v : e[cur.second])
            {
                --in[v];
                if (!in[v])
                    q.push(mp(v > cur.second ? cur.first : cur.first + 1, v));
            }
        }
        if (cnt < n)
            return -1;
        return res;
    }
    
    int main(int argc, char const *argv[])
    {
        int T = read();
        while (T--)
            printf("%d\n", solve());
        return 0;
    }
    

    D. Xor of 3

    题意:给你一个长为 \(n\)\(01\) 序列,你可以进行以下操作至多 \(n\) 次直至序列中所有元素均为 \(0\)

    • \(1\)\(n−2\) 中选择一个索引 \(i\)
    • \(a_i = a_{i+1} = a_{i+2} = a_i⊕a_{i+1}⊕a_{i+2}\)

    判断是否有解,若有解,输出任一解决方案。

    题目分析:先考虑变换前后的不变量,首先每次变换均不会改变序列的奇偶性,要么少两个 \(1\) 要么多两个 \(1\) ,所以原序列若存在奇数个 \(1\) 则无解。

    偶数个 \(1\) 情况下,考虑一段连续的 \(1\)

    • 如果是偶数个 \(1\) ,由于本题序列的奇偶不变性,一定可以将这段 \(1\) 全消为 \(0\)
    • 如果是奇数个 \(1\) ,那么不能靠自己消完,所以要往后每次把两个 \(0\) 变成 \(1\) ,直到遇到 \(101\) 这种情况,把 \(101\) 变成 \(000\) 后,前面的 \(1\) 只有偶数个,即转换为了上述情况,就可以消完了

    最后特判一下 \(0、0、0 \cdots 1、1、1\) 情况就好,由于末尾段 \(1\) 的个数必为偶数个,所以前面只要存在 \(0\) 就可以全部消完,那么唯一无解的情况下即是序列转化为了全 \(1\) 序列(如 \([1,0,0,1]\) )。

    AC代码

    #include <bits/stdc++.h>
    #define rep(i, x, y) for (register int i = (x); i <= (y); i++)
    #define down(i, x, y) for (register int i = (x); i >= (y); i--)
    
    char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
    #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    inline int read()
    {
        int x = 0, f = 1;
        char ch = getchar();
        while (!isdigit(ch))
        {
            if (ch == '-')
                f = -1;
            ch = getchar();
        }
        while (isdigit(ch))
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    
    void solve()
    {
        int n = read(), cnt = 0;
        std::vector<int> a(n + 1);
        std::vector<int> ans;
        for (int i = 1; i <= n; ++i)
            if (a[i] = read())
                ++cnt;
        if (cnt & 1)
        {
            puts("NO");
            return;
        }
        cnt = 0;
        for (int i = 1; i <= n; ++i)
        {
            if (a[i])
                ++cnt;
            else if (cnt & 1)
            {
                if (a[i + 1])
                {
                    a[i - 1] = a[i + 1] = 0;
                    for (int j = i - 1; j >= i - cnt; j -= 2)
                        ans.push_back(j), a[j] = a[j + 1] = 0;
                    cnt = 0;
                }
                else
                {
                    ans.push_back(i - 1);
                    a[i] = a[i + 1] = 1;
                    ++cnt;
                }
            }
            else
            {
                for (int j = i - 2; j >= i - cnt; j -= 2)
                    ans.push_back(j), a[j] = a[j + 1] = 0;
                cnt = 0;
            }
        }
        if (cnt)
        {
            if (cnt == n)
            {
                puts("NO");
                return;
            }
            for (int i = n - cnt; i <= n - 2; i += 2)
                ans.push_back(i);
        }
        puts("YES");
        printf("%d\n", ans.size());
        for (auto x : ans)
            printf("%d ", x);
        if (ans.size())
            puts("");
    }
    
    int main(int argc, char const *argv[])
    {
        int T = read();
        while (T--)
            solve();
        return 0;
    }
    
  • 相关阅读:
    动态表单功能
    IDEA2019版Run Dashboard调出方案
    js页面传递参数为中文乱码问题解决方法
    layui 一行多列控件时使用table布局
    npm 安装包失败 --- 清除npm缓存
    解析数据库连接字符串 (将Data Source、Initial Catalog、User ID、Password取出)
    SQL SERVER 存储过程语法
    mvc5 跨域访问
    钟表
    MVC session过期如何处理跳转(转)
  • 原文地址:https://www.cnblogs.com/Foreign/p/15321444.html
Copyright © 2011-2022 走看看