https://www.luogu.com.cn/problem/T145688?contestId=33886
题目背景
原题面:
\color{gray}\text{zrmpaul}zrmpaul has an array consisting of nn integers: a_1,a_2,...,a_na1,a2,...,an. The initial value of a_iai is i(1\le i\le n)i(1≤i≤n). There are mm operations, including four types as follows.
Type 11: 1
sort the array.
Type 22: 2
sort the array and reverse it.
Type 33: 3 x y
swap a_x,a_yax,ay. It is guaranteed that xx is not equal to yy, and 1\leq x ,y \leq n1≤x,y≤n.
Type 44: 4
reverse the array.
You need to output the array after mm operations.
First line with two intergers n,m(1\leq n,m\leq 10^6)n,m(1≤n,m≤106).
Next mm lines are the operations.
One line, nn numbers, the array.
题目描述
小 Z 有一个下标从 11 开始并且长度为 nn 的序列,初始时下标为 ii 位置的数字为 ii。有 mm 个操作,每个操作会是以下四种之一。
1
对序列从小到大进行排序。2
对序列从小到大进行排序后将其翻转,(译者注:就是从大到小排序)。3 x y
将下标为 x,yx,y 的数交换位置。保证 x\neq yx=y 且 1\le x,y\le n1≤x,y≤n。4
将序列翻转。
你要输出在 mm 次操作后的序列。
输入格式
第一行两个整数 n,mn,m ,表示序列的长度以及操作的数量。
接下来 mm 行,每行一个操作。保证操作合法。
输出格式
一行包含 nn 个整数,表示操作后的序列。
输入输出样例
输入 #1复制
5 5 1 2 3 2 4 4 3 1 5
输出 #1复制
5 4 3 2 1
说明/提示
【数据范围】
【本题采用捆绑测试】
subtask 1(24pts): 1\leq n,m\leq 2 \times 10^31≤n,m≤2×103 。
subtask 2(13pts): 没有操作三。
subtask 3(63pts): 1\leq n,m\leq 10^61≤n,m≤106 。
【样例解释】
序列经过的操作为:
1, 2, 3, 4, 51,2,3,4,5
1, 2, 3, 4, 51,2,3,4,5
5, 4, 3, 2, 15,4,3,2,1
5, 2, 3, 4, 15,2,3,4,1
1, 4, 3, 2, 51,4,3,2,5
5, 4, 3, 2, 15,4,3,2,1
思路:当然第一眼的时候思路是暴力辣。然后看了看范围肯定只能拿pretest1的分。然后就接着想。
发现如果3,4的后面有1或者2,那么这时候3,4的操作都是抵消的,就是说这些3的操作或者4的操作都是无效的。知道了这一点之后你会发现如果后面没有3,那么1,2,4的操作就只有x=0(正序),x=1(反序)之间来回变换,这里直接O(1)就可以了,不用那些sort的nlogn。
当时卡我的reverse操作,比如现在进行了3操作,接下来有4操作,再有3操作,再有4操作,这时候的swap和reverse怎么处理呢?当时想了下应该是把l和r根据长度减下换了,但是又觉得不等价。于是往其他方向瞎想gg。
正解就是比如现在是x=0,那么换就直接换l和r的两个数字,如果这时候出了4反序,无所谓标记一下x=1,再出了3交换,这时候交换n-l+1和n-r+1的地方就是等价的,若再出4,就标记x=0,这时候如果交换就换l和r的。这样就等价了...(555我太菜了
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e6+100;
typedef long long LL;
LL a[maxn];
LL l[maxn],r[maxn],op[maxn];
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,m;cin>>n>>m;
for(LL i=1;i<=n;i++) a[i]=i;
for(LL i=1;i<=m;i++)
{
cin>>op[i];
if(op[i]==3) cin>>l[i]>>r[i];
else l[i]=r[i]=0;
}
LL pos=1;
for(LL i=m;i>=1;i--)
{
if(op[i]==1||op[i]==2) {pos=i;break;}
}
LL x=0;//正序
if(op[pos]==1) x=0;
else x=1-x;
for(LL i=pos+1;i<=m;i++)
{
if(op[i]==3)
{
if(x==0) swap(a[l[i]],a[r[i]]);
else swap(a[n-l[i]+1],a[n-r[i]+1]);
}
else x=1-x;
}
if(x==0)
{
for(LL i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
}
else{
for(LL i=n;i>=1;i--) cout<<a[i]<<" ";
cout<<endl;
}
return 0;
}