ABC258C 题解

题面

AT_abc258_c [ABC258C] Rotation

题目描述

给定正整数 \(N,Q\),以及一个长度为 \(N\) 的由小写英文字母组成的字符串 \(S\)

请处理 \(Q\) 个如下所述的查询。查询有以下两种类型之一:

  • 1 x:将 \(S\) 的末尾字符删除,并插入到开头,连续执行 \(x\) 次。
  • 2 x:输出 \(S\) 的第 \(x\) 个字符。

输入格式

输入以如下格式从标准输入给出。

\(N\) \(Q\) \(S\) \(\mathrm{query}_1\) \(\mathrm{query}_2\) \(\vdots\) \(\mathrm{query}_Q\)

每个查询的格式如下,其中 \(t\)\(1\)\(2\)

\(t\) \(x\)

输出格式

对于每个 2 x 类型的查询,输出答案,每个答案占一行。

输入输出样例 #1

输入 #1

3 3
abc
2 2
1 1
2 2

输出 #1

b
a

输入输出样例 #2

输入 #2

10 8
dsuccxulnl
2 4
2 7
1 2
2 7
1 1
1 2
1 3
2 5

输出 #2

c
u
c
u

说明/提示

数据范围

  • \(2 \leq N \leq 5 \times 10^5\)
  • \(1 \leq Q \leq 5 \times 10^5\)
  • \(1 \leq x \leq N\)
  • \(|S| = N\)
  • \(S\) 由小写英文字母组成。
  • 至少有一个 2 x 类型的查询。
  • \(N,Q,x\) 均为整数。

样例解释 1

\(1\) 个查询时,\(S\)abc,因此输出第 \(2\) 个字符 b。第 \(2\) 个查询时,\(S\)abc 变为 cab。第 \(3\) 个查询时,\(S\)cab,因此输出第 \(2\) 个字符 a

由 ChatGPT 4.1 翻译

这是一道橙题,但是我没有自己做出它,我依稀记得有一个公式可以快速的解决它的一部分,确实是这样,后面会讲到他。

这题核心在于一个发现:
假设有字符串abc,模拟一下op == 1的过程,每次移动一个。
abc a是起点。
cab a左边的c变成了起点。
bca c左边的b又边成了起点。
(均为循环移位)

发现了吗,每一次op == 1的操作不过,只是在将起点循环左移
公式自然显而易见,会在代码里。

用于解决一个起点b右边p的单位的下标(p可能大于总长n,因为循环移位,例如p = 6时在末位p = 7时则在首位)的公式:

(b + p - 1) % n + 1

蒙了半天才蒙到的
对比(b + p) % n
(b + p - 1) % n + 1:取值范围1 ~ n
(b + p) % n:取值范围0 ~ n - 1

#include <bits/stdc++.h>

using namespace std;

signed main() {
    int n, T;
    cin >> n >> T;
    string s;
    cin >> s;
    s = '!' + s;

    int b = 0;
    while (T--) {
        int op;
        cin >> op;
        if (op == 1) {
            int y;
            cin >> y;
            y %= n;
            b = (b - y + n) % n; // 取模当心负数!
        } else {
            int p;
            cin >> p;
            cout << s[(b + p - 1) % n + 1] << '\n'; // 讲过了
        }
    }
    return 0;
}

误区警示!

写题解的时候才发现。
b = 0是合法的,b的取值范围是[0, n - 1],p才是[1, n],毕竟这个字符串默认第一个字符的下标为1
p是第一个字符,不是后一个字符
上面的讲述只是一种好的思考方式(当然,也是正确的,但是和代码的思路有所不同)。
在代码里b是一个向右的有效偏移量,起点的下标怎么可能是0呢?
如果b = 0就是说明,当前字符串经过多次操作后,新字符串和读入的字符串是一样的
换一种思路,b也可以理解为通过\(O(1)\)的操作代替了\(O(n)\)改变每个字符的下标!(例如b = 1代表全体+1,原n变1)。

总结

1.如果发现某题好像可以用某个模板解决一定不要急于套模板
2.还是这句话,不审清题,不开始下一步执行,从现在开始无论难度至少读两次题
3.代码AC不代表真的理解了,所以复盘是绝对正确,且不浪费时间的。
4.取模当心负数

posted @ 2026-05-03 17:20  PCMSFV  阅读(6)  评论(0)    收藏  举报