[关闭]
@AkamemakA 2022-07-03T14:08:27.000000Z 字数 1284 阅读 87

Atcoder 题解

Atcoder Beginner Contest 258 problem C 题解


题目大意

给定一个由小写字母构成的字符串,有以下两种操作,每个操作输入两个数

样例输入1

  1. 3 3
  2. abc
  3. 2 2
  4. 1 1
  5. 2 2

样例输出1

  1. b
  2. a

样例解释1

样例输入2

  1. 10 8
  2. dsuccxulnl
  3. 2 4
  4. 2 7
  5. 1 2
  6. 2 7
  7. 1 1
  8. 1 2
  9. 1 3
  10. 2 5

样例输出2

  1. c
  2. u
  3. c
  4. u

数据范围


解析

对于这个题,我们可以来了解一些string的函数:

用这两个函数,我们可以写出这道题。不过这两个函数复杂度为的,也就是说,总的时间复杂度近似于,自然是不可接受的。(不过本人还是写了,放在下面。)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,q;
  4. string s;
  5. int main()
  6. {
  7. cin>>n>>q;
  8. cin>>s;
  9. while(q--){
  10. int ops,x;
  11. cin>>ops>>x;
  12. if(ops==1){
  13. string ss=s.substr(n-x,x);//取出后x个字符
  14. s.erase(n-x,x);//删去后x个字符
  15. ss+=s;//将这x个字符加到串首
  16. s=ss;//原串
  17. }
  18. else cout<<s[x-1]<<endl;//输出
  19. }
  20. }

(亲测可过个点)

因此,我们要来想一些其他的办法。

不难发现,如果之前没有过删除添加操作的话,那么输出的字符就是从字符串的第一个字符开始数个字符。

但是如果进行过删除添加操作,我们可以将字符串看作不动,而把数字符的起点向左移动(若移出了字符串左端则从右端开始继续移),具体见下图:

此处输入图片的描述

因此,本题的时间复杂度便降到了,完美解决。

代码实现

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,q;
  4. string s;
  5. int main()
  6. {
  7. cin>>n>>q;
  8. cin>>s;
  9. int f=0; //数字符的起点
  10. while(q--){
  11. int ops,x;
  12. cin>>ops>>x;
  13. if(ops==1){
  14. f-=x;
  15. f=(f+n)%n; //向左移x个字符,若超出左端则从右端开始继续移
  16. }
  17. else {
  18. int t=f+x; //从f开始数x个
  19. if(t>n) t-=n; //若超出右端,则从左端开始继续数
  20. //注意:千万不能写 t%=n,因为如果t恰好等于n,那么模出来t=0,输出的就会是s[-1],会WA
  21. cout<<s[t-1]<<endl;
  22. }
  23. }
  24. return 0;
  25. }

完结撒花~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注