@AkamemakA
2022-07-03T14:08:27.000000Z
字数 1284
阅读 87
Atcoder
题解
给定一个由小写字母构成的字符串,有以下两种操作,每个操作输入两个数:
3 3
abc
2 2
1 1
2 2
b
a
10 8
dsuccxulnl
2 4
2 7
1 2
2 7
1 1
1 2
1 3
2 5
c
u
c
u
对于这个题,我们可以来了解一些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],会WA
cout<<s[t-1]<<endl;
}
}
return 0;
}
完结撒花~