题目
有一个长为n的序列x现知如下现种操作:
a操作:将序列中最后一个数移到最前面:
b操作:将序列第三个数移到最前面。
连续的k次操作用ka或kb的形式表示。给出m次这样连续的操作,请输出操作后这个序列是什么。
输入描述
第一行两个整数n和m,表示序列长度和连续操作的次数。
第二行n个整数x1, x2……, xn表示这个序列
第三行m个形如ka和kb的字符串,每两个字符串之间有一个空格,行末无空格,按输入顺序表示一次连续的操作。
对于全部数据,1<=n, m <= 5*10^4, 1<=k<=10^9, 1<=xi <=10^5
输出描述
输出一行n个整数,表示m次连续操作之后的序列。注意输出时序列中两个数之间输出一个空格,行末不要 输出多余的空格。
思路
这道题我认为是一个旋转数组/旋转字符串的变体。只不过在act b中,不是将末尾的数字移到最前,而是第三个数字。
本质是一样的,就是移动k次,就是移动(k%size)次。而移动的次数就相当于,反转整体后,分别反转前k个数字,和后面的数字。
有一个问题是。我不知道当n小于3时,如何操作act b。欢迎大家在评论区讨论。
代码实现细节
- 用什么数据结构?
- 考虑到不用数据结构,而且是旋转过程,使用字符串是最合适的。
- 考虑到要对每个字符串和每个操作进行分别的处理,应该将字符串储存在vector中,方便后续的读取和操作。这样就不用考虑输入中的空格了。
- 题目给出了n和m,即序列的长度和操作的个数,其实在暗示可以用n和m记录和控制赋值过程。
- 如何处理提取操作类型和操作次数?
- 由于每个操作指令都是由数字和字母a或b组成。所以可以将最后一个字符记录为operation,然后弹出。剩下的字符串使用stoi()函数,转换成整数,就得到了操作次数。
代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
void act(vector<int>& sequence, int k, char op){
int size;
if (op=='a'){
size = sequence.size();
}
if(op=='b'){
size = 3;
}
k = k % size;
// 重复k次将指定位置的元素移到最前面;
reverse(sequence.begin(), sequence.begin()+size);
reverse(sequence.begin(), sequence.begin()+k);
reverse(sequence.begin()+k, sequence.begin()+size);
}
int main(){
//
int n, m;
cin>>n>>m;
vector<int> sequence;
while(n--){
int temp;
cin>>temp;
sequence.push_back(temp);
}
vector<string> acts;
while(m--){
string temp;
cin>>temp;
acts.push_back(temp);
}
for(string a:acts){
char operation = a.back();
a.pop_back();
int k = stoi(a);
act(sequence, k, operation);
}
string T;
for(int num:sequence){
T+=to_string(num);
T+=" ";
}
T.pop_back();
cout<<T<<endl;
}