V(1982): 小M的移动硬盘

V(1982): 小M的移动硬盘

      Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 171     Solved: 66    

Description

最近小M买了一个移动硬盘来储存自己电脑里不常用的文件。但是他把这些文件一股脑丢进移动硬盘后,觉得这些文件似乎没有被很好地归类,这样以后找起来岂不是会非常麻烦?
小M最终决定要把这些文件好好归类,把同一类地移动到一起。所以现在小M有了这几种操作:
1 u 表示把编号为u的文件放到最上面
2 u 表示把编号为u的文件放到最下面
3 u v 表示把编号为u的文件放到编号为v的文件的后面
已知在最开始的时候,1号文件到n号文件从上往下排布
现在小M已经给出了他所进行的所有操作,你能告诉他操作之后的序列是会变成什么样子吗?

Input

第一行为一个数字T(T<=10)表示数据组数
第二行为两个数字n、m(1<=n,m<=300000)表示序列长度和小M的操作次数
接下来m行每行两个或三个数字,具体含义见题面
保证数据合法

Output

输出一行表示小M操作结束后的序列

Sample Input

1
10 5
1 5
2 3
2 6
3 4 8
3 1 3

Sample Output

5 2 7 8 4 9 10 3 1 6

应该很明显就可以看出来是对链表的基本操作。只是本人比较懒,创建链表嫌麻烦,c++的STL似乎也没有链表的模板类,所以我用数组模拟了链表,算是用的双链表吧,其实单链表好像也是可以解决的。我用了两个数组分别记录前驱和后继。

#include<iostream>
using namespace std;
int le[300005], ri[300005];//分别放前驱和后继
int m;
//别纠结这个名字为什么会是swap,原谅我英语差
void swap(int x, int y)//双链表将x插入到y后面
{
	le[ri[x]] = le[x];//自己画个链表应该就能明白了;\
	le[x]为x节点的前驱,ri[x]为x节点的后继
	ri[le[x]] = ri[x];
	le[x] = y;
	ri[x] = ri[y];
	le[ri[y]] = x;
	ri[y] = x;
}
void print()//输出
{
	int mid=ri[0];
    printf("%d",ri[0]);
    while (ri[mid] < m+1)
    {
        printf(" %d", ri[mid]);
        mid=ri[mid];
    }
    printf("\n");
}
int main()
{
	int t;
	scanf ("%d", &t);
	while (t--)
	{
		int n;
		scanf ("%d%d", &m, &n);
		for (int i =1; i <=m; i++)//记录每个点的前驱与后继
		{
			le[i] = i-1;
			ri[i] = i+1;
		}
		ri[0] = 1;//0是头结点
		le[m + 1] = m;//m-1是空,即使用链表时的NULL
		for (int i = 0; i <n; i++)
		{
			int d;
			int x, y;
			scanf ("%d", &d);
			switch(d)
			{
				case 1:
				scanf ("%d",&x);
				swap(x,0);//将x节点插入到头结点的后面,即将x放到第一个
				break;
				case 2:
				scanf ("%d", &x);
				le[ri[x]] = le[x];//没办法用swap函数,只能自己写了
				ri[le[x]] = ri[x];
				ri[x] = m + 1;
				le[x] = le[m +1];
				ri[le[m + 1]] = x;
				le[m +1] = x;
				break;
				case 3:
				scanf ("%d%d", &x, &y);//x放到y后面
				swap(x,y);
				break;
			}
		}
		print();
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值