题目描述
小 Z 有一个下标从 1 开始并且长度为 n 的序列,初始时下标为 i 位置的数字为 i。有 m 个操作,每个操作会是以下四种之一。
- 对序列从小到大进行排序。
- 对序列从小到大进行排序后将其翻转,(译者注:就是从大到小排序)。
- x y 将下标为 x,y 的数交换位置。保证 x≠y且 1≤x,y≤n。
- 将序列翻转。
你要输出在 m 次操作后的序列。
输入格式
第一行两个整数 n,m ,表示序列的长度以及操作的数量。
接下来 m 行,每行一个操作。保证操作合法。
输出格式
一行包含 n 个整数,表示操作后的序列。
思路
首先我们从后往前寻找最后一个1 or 2,并从这里开始暴力求解,重点是翻转在最后处理,但暴力操作3时要看翻转了多少次,奇数次逆序,偶数次正序(这里正反序是指这一段的最开始,不管开始的1,2),偶数次交换第x个,第y个,奇数次交换第n-x+1,n-y+1个。
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[1000006],b[1000006];
int c[1000006][2];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n,m,o=1,o2=0;
cin>>n>>m;
b[0]=1;
for (int i=1;i<=m;i++)
{
cin>>b[i];
if (b[i]==3)
{
cin>>c[i][0]>>c[i][1];
}
}
for (int i=1;i<=n;i++)
{
a[i]=i;
}
for (int i=m;i>=0;i--)
{
if (b[i]<=2)
{
o2=i;
break;
}
}
if (b[o2]==2)
{
sort(a+1,a+1+n,cmp);
}
for (int i=o2;i<=m;i++)
{
if (b[i]==3)
{
if (o==1) swap(a[c[i][0]],a[c[i][1]]);
else swap(a[n-c[i][0]+1],a[n-c[i][1]+1]);
}
if (b[i]==4) o=-o;
}
int y=(o==1?1:n),y2=(o==1?n:1);
for (int i=y;i!=y2;i+=o)
{
cout<<a[i]<<' ';
}
cout<<a[y2]<<endl;
return 0;
}