@AkamemakA
2022-07-03T14:08:27.000000Z
字数 1284
阅读 109
Atcoder 题解
给定一个由小写字母构成的字符串,有以下两种操作,每个操作输入两个数:
3 3abc2 21 12 2
ba
10 8dsuccxulnl2 42 71 22 71 11 21 32 5
cucu
对于这个题,我们可以来了解一些string的函数:
用这两个函数,我们可以写出这道题。不过这两个函数复杂度为的,也就是说,总的时间复杂度近似于,自然是不可接受的。(不过本人还是写了,放在下面。)
#include<bits/stdc++.h>using namespace std;int n,q;string s;int main(){cin>>n>>q;cin>>s;while(q--){int ops,x;cin>>ops>>x;if(ops==1){string ss=s.substr(n-x,x);//取出后x个字符s.erase(n-x,x);//删去后x个字符ss+=s;//将这x个字符加到串首s=ss;//原串}else cout<<s[x-1]<<endl;//输出}}
(亲测可过个点)
因此,我们要来想一些其他的办法。
不难发现,如果之前没有过删除添加操作的话,那么输出的字符就是从字符串的第一个字符开始数个字符。
但是如果进行过删除添加操作,我们可以将字符串看作不动,而把数字符的起点向左移动(若移出了字符串左端则从右端开始继续移),具体见下图:

因此,本题的时间复杂度便降到了,完美解决。
#include<bits/stdc++.h>using namespace std;int n,q;string s;int main(){cin>>n>>q;cin>>s;int f=0; //数字符的起点while(q--){int ops,x;cin>>ops>>x;if(ops==1){f-=x;f=(f+n)%n; //向左移x个字符,若超出左端则从右端开始继续移}else {int t=f+x; //从f开始数x个if(t>n) t-=n; //若超出右端,则从左端开始继续数//注意:千万不能写 t%=n,因为如果t恰好等于n,那么模出来t=0,输出的就会是s[-1],会WAcout<<s[t-1]<<endl;}}return 0;}
完结撒花~