题目链接:https://atcoder.jp/contests/abc158/tasks/abc158_d
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 400 points
Takahashi has a string S consisting of lowercase English letters.
Starting with this string, he will produce a new one in the procedure given as follows.
The procedure consists of Q operations. In Operation ii (1≤i≤Q), an integer Tiis provided, which means the following:
If Ti=1Ti=1: reverse the string SS.
If Ti=2Ti=2: An integer FiFi and a lowercase English letter CiCi are additionally provided.
Help Takahashi by finding the final string that results from the procedure.
Input is given from Standard Input in the following format:
SS
QQ
Query
::
Query
In the 3-rd through the (Q+2)-th lines, QueryiQueryi is one of the following:
11
which means Ti=1, and:
22 FCi
which means Ti=2.
Print the resulting string.
a
4
2 1 p
1
2 2 c
1
cpa
There will be Q=4 operations. Initially, S is a
.
Operation 1: Add p
at the beginning of S. S becomes pa
.
Operation 2: Reverse S. S becomes ap
.
Operation 3: Add c
at the end of S. S becomes apc
.
Operation 4: Reverse S. S becomes cpa
.
Thus, the resulting string is cpa
.
a
6
2 2 a
2 1 b
1
2 2 c
1
1
aabc
There will be Q=6Q=6 operations. Initially, SS is a
.
Operation 11: S becomes aa
.
Operation 22: S becomes baa
.
Operation 33: S becomes aab
.
Operation 44: S becomes aabc
.
Operation 55: S becomes cbaa
.
Operation 66: S becomes aabc
.
Thus, the resulting string is aabc
.
y
1
2 1 x
xy
题解写了很多,都是废话。。。。。
直接看大佬代码:
#include
using namespace std;
int main()
{
string s;
cin>>s;
int Q;
cin>>Q;
string T;
for(int i=1;i<=Q;i++)
{
int t;
cin>>t;
if(t==1)
{
swap(s,T);
}
if(t==2)
{
int f;
char c;
cin>>f>>c;
if(f==1) T.push_back(c);
if(f==2) s.push_back(c);
}
}
reverse(T.begin(),T.end());
cout<
不知道其他大佬怎么写的,我用string的字符串拼接写的,结果超时;超时的原因我总结一下有两点:
解决第一个问题的关键在于不能每一次都对字符串进行翻转,可以用cnt记录反转操作出现的次数,当cnt为偶数时,说明字符串没有进行反转,则进行添加操作时,可以正常进行;当cnt为奇数时,说明字符串进行了一次反转,那么进行当前添加操作时,应该按相反的操作进行;比如字符串abcd,常规操作:将他进行三次反转之后是,dcba,我在开头加上e,结尾加上f,变成edcbaf;另一种操作,cnt为偶数,则执行e加到开头这个操作时,要按相反的来,同理,f也相反,那就变成fabcde,由于cnt为奇数,抵消之后还剩一次反转操作,那么进行翻转得到edcba;并且再最后输出的时候要把后缀变前缀,中间反转,前缀变后缀
上面可能说的太罗嗦了 ,我举个简单例子吧;
原始字符串:abcd 执行开头加e,反转,结尾加f,反转,开头加m,结尾加n,反转;(cnt为执行当前操作之前反转的次数)
开头加e,cnt为0,e加入前缀;(此时前缀为e)
结尾加f,cnt为1,f加入前缀;(此时前缀为fe)
开头加m,cnt为2,m加入前缀;(此时前缀为mfe)
结尾加n,cnt为2,n加入后缀;(此时后缀为n)
由于最后cnt为3,所以输出的时候要反转,先输出反转后缀n,然后中间反转dcba,前缀反转efm;
over....
然后就是字符串的拼接,
两种拼接方式:
s+=ss; //这种拼接为引用拼接
s=s+ss; //重新生成了一个对象的拼接
前者比后者快;
当你把当前这个字符ss加到开头的操作是s=ss+s,加到结尾的操作是s+=ss;由于原字符串s长度比较大的原因,会造成拼接效率下降,所以这里如果用原字符串进行拼接,不妥;可以定义一个前缀字符串a保存放在开头的字符,一个后缀字符串b保存放在结尾的字符;这样拼接的时候字符串长度大大下降,效率大大提升;
(可能这一题并没有卡这个地方,也许有别的更高效便捷的做法,欢迎大佬们指出qaq~)
#include
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(false);
string s,ss;
string a,b;
cin>>s;
int q,cnt=0;
cin >>q;
while(q--)
{
int t;
cin >>t;
if(t==1) cnt++;
else
{
int f;
cin >>f>>ss;
if(f==1)
{
if(cnt%2) b+=ss;
else a=ss+a;
}
else
{
if(cnt%2) a=ss+a;
else b+=ss;
}
}
}
int x=a.size(),y=b.size(),z=s.size();
if(cnt%2)
{
for(int i=y-1;i>=0;i--) cout <=0;i--) cout <=0;i--) cout <