P6823 zrmpaul Loves Array 题解
题目链接
https://www.luogu.com.cn/problem/P6823
题目分析
这道题是一个很不错的锻炼代码能力的题,主要思路是模拟。
注意:如果中出现任意一个 (1) 或 (2) ,那么它前面的顺序就会被打乱。所以我们只要在所有操作中从后往前找第一个 (1) 或 (2) ,来确定起始位置。
我们可以把序列用数组 len1[i]
来存储。因为下面会进行翻转操作,为了方便,我们可以再开一个数组 len2[i]
来帮助操作。
对于操作1:直接正序存入数组1。
对于操作2:直接倒序存入数组1。
对于操作3:可以用 swap 函数交换数组中两数的位置。
对于操作4:我们可以把数组1中的数正序存入数组2,再把数组2反向输出到数组1.
在这里需要注意一点,如果有两个操作4挨在了一起,那么它们两个就可以相互抵消。我们要判断有无这种情况。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1000035;
struct node{ //为了判断最后的1或2,我们需要把每种操作存起来
ll id,x,y;
}t[maxn];
ll len1[maxn],len2[maxn];
int main()
{
ll n,m;
n=read();
m=read();
for(int i=1;i<=n;++i)//先初始化
{
len1[i]=i;
}
ll cz=0;//cz用来记录操作种类
for(ll i=1;i<=m;++i)
{
cz=read();
t[i].id=cz;
if(cz==3)
{
t[i].x=read();
t[i].y=read();
}
}
ll left; //left记录最后的1或2 出现的位置
for(ll i=m;i>=1;--i)
{
if(t[i].id==1 || t[i].id==2)
{
left=i;//记录
break;
}
}
for(ll k=left;k<=m;++k)
{
if(t[k].id==1)
for(ll i=1;i<=n;++i)
len1[i]=i;
else if(t[k].id==2)
{
ll j=n;
for(int i=1;i<=n;++i)
{
len1[i]=j;
j--;
}
}
else if(t[k].id==4)
{
if(t[k+1].id==4) //此处特判两个4挨在一起的情况
{
k++; //这里k只能+1,因为continue之后k还会+1,这样才一共+2
continue;
}
ll j=n;
for(ll i=1;i<=n;++i) //倒序存入数组2
{
len2[i]=len1[j];
j--;
}
for(int i=1;i<=n;++i) //再返回到数组1
{
len1[i]=len2[i];
}
}
else if(t[k].id==3)
{
ll xx=t[k].x;
ll yy=t[k].y;
swap(len1[xx],len1[yy]); //交换两数的位置
}
}
for(ll i=1;i<=n;++i)
printf("%lld ",len1[i]); //输出操作完毕的序列
return 0;
}
解决方法:卡常 or 吸氧