1 solutions

  • 2
    @ 2023-12-23 12:13:37

    这个题,yydj鉴定为大模拟(于是我决定给代码上点强度

    题意

    给定一个长度为 NN 的字符串 ss,其中每个字符对应一种颜色(共 MM 种)。对于每一种颜色,执行旋转操作并放回原串中。输出操作后的字符串。

    思路

    按照题意模拟,没什么好说的。建议将每种颜色分开处理。

    实现

    1. 按照颜色分类,将原串 ss 划分为 MM 个新字符串。
    2. 对每个新字符串执行旋转操作。
    3. 按照原串的颜色顺序 顺次读取每种颜色的新字符串,并输出。(详见代码)

    另外,putchar(x) 表示输出单个字符x。(x是个变量)

    #include <iostream>
    using namespace std;
    const int N = 2e5+10;
    // 使用自定义namespace 维护不同颜色字符串的分割、旋转、合并操作
    namespace Split {
        string spl[N];  // 存放 每种颜色有哪些字符
        int pos[N];  // pos[u]表示 已经输出了pos[u]-1个颜色为u的字符
        // 在颜色为u的字符串中插入字符c
        inline void push(int u, char c) {
            spl[u].push_back(c);
        }
        // 旋转操作
        inline void rotate(int u) {
            int len = spl[u].size();
            char t = spl[u][len-1];
            for(int i=len;i>0;--i)
                spl[u][i] = spl[u][i-1];
            spl[u][0] = t;
        }
        // 返回 颜色为u的 还没输出的 最靠前的 字符
        inline char pop(int u) {
            return spl[u][pos[u]++];
            // 这里[pos[u]++]会在返回后自动跳到下一位
            // 也就是说 当前颜色 已输出字符的数量 增加了1
        }
    }
    int n, m, col[N];
    char s[N];
    int main() {
        scanf("%d%d%s", &n, &m, s+1);  // s+1表示直接从下标1开始读入字符串
        for(int i=1;i<=n;++i) {
            scanf("%d", &col[i]);
            Split::push(col[i], s[i]);  // 将第i个字符插入颜色为col[i]的集合中
        }
        // 对于每一种颜色,执行旋转操作
        for(int i=1;i<=m;++i)
            Split::rotate(i);
        for(int i=1;i<=n;++i)
            putchar(Split::pop(col[i]));  // 从颜色集合中取出字符,并输出
            // pop函数保证了返回值相对集合内元素有序(不重不漏),也就是相对原串是有序的
        return 0;
    }
    
    • @ 2023-12-24 11:11:59

      自定义 namespace 估计C23要很久以后才会用到,不过先自学一下也行 [笑哭]

    • @ 2023-12-24 11:12:34

      大模拟??就一个小小的模拟吧 👀️

  • 1

Information

ID
966
Time
1000ms
Memory
256MiB
Difficulty
9
Tags
(None)
# Submissions
9
Accepted
5
Uploaded By