Loading

luoguP6823 zrmpaul Loves Array 题解

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 吸氧

posted @ 2020-09-08 17:46  EdisonBa  阅读(166)  评论(0编辑  收藏  举报