V: 小M的移动硬盘
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
思路:构造结构体,保存前驱结点和后继节点(注意插入时的特殊情况)
#include<cstdio>
#include<queue>
using std::priority_queue;
const int MAX = 300005;
struct Node{
int number;
int pre; //之前的结点
int pro; //之后的节点
};
struct Node P[MAX];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
{
P[i].number = i;
P[i].pre = i - 1;
P[i].pro = i + 1;
}
struct Node *Head = &P[1];
struct Node *Tail = &P[n];
for (int i = 0; i < m; i++)
{
int a, b, c;
int pre, pro;
scanf("%d", &a);
switch(a)
{
case 1:
scanf("%d", &b);
if (b != Tail->number && b != Head->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
P[pro].pre = pre;
P[b].pre = Head->pre;
P[b].pro = Head->number;
Head->pre = b;
Head = &P[b];
}
else if (b == Tail->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
Tail = &P[pre];
P[b].pre = Head->pre;
P[b].pro = Head->number;
Head->pre = b;
Head = &P[b];
}
break;
case 2:
scanf("%d", &b);
if (b != Head->number && b != Tail->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
P[pro].pre = pre;
P[b].pre = Tail->number;
P[b].pro = Tail->pro;
Tail->pro = b;
Tail = &P[b];
}
else if (b == Head->number)
{
pro = P[b].pro;
pre = P[b].pre;
P[pro].pre = pre;
Head = &P[pro];
P[b].pre = Tail->number;
P[b].pro = Tail->pro;
Tail->pro = b;
Tail = &P[b];
}
break;
case 3:
scanf("%d %d", &b, &c);
if (b != Head->number && b != Tail->number && c != Head->number && c != Tail->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
P[pro].pre = pre;
pro = P[c].pro;
P[c].pro = b;
P[pro].pre = b;
P[b].pre = c;
P[b].pro = pro;
}
if (b == Head->number && c != Tail->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pro].pre = pre;
Head = &P[pro];
pro = P[c].pro;
P[c].pro = b;
P[pro].pre = b;
P[b].pre = c;
P[b].pro = pro;
}
if (b == Head->number && c == Tail->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pro].pre = pre;
Head = &P[pro];
P[c].pro = b;
P[b].pre = c;
P[b].pro = P[c].pro;
Tail = &P[b];
}
if (b == Tail->number && c == Head->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
Tail = &P[pre];
pro = P[c].pro;
P[b].pro = pro;
P[pro].pre = b;
P[b].pre = c;
P[c].pro = b;
}
if (b == Tail->number && c != Head->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
Tail = &P[pre];
pro = P[c].pro;
P[pro].pre = b;
P[b].pro = pro;
P[b].pre = c;
P[c].pro = b;
}
if (b != Head->number && b != Tail->number && c == Head->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
P[pro].pre = pre;
pro = P[c].pro;
P[c].pro = b;
P[pro].pre = b;
P[b].pre = c;
P[b].pro = pro;
}
if (b != Head->number && b != Tail->number && c == Tail->number)
{
pre = P[b].pre;
pro = P[b].pro;
P[pre].pro = pro;
P[pro].pre = pre;
pro = P[c].pro;
P[c].pro = b;
P[b].pre = c;
P[b].pro = pro;
Tail = &P[b];
}
break;
}
}
int num = Head->number;
for (int i = 0; i < n; i++)
{
printf("%d ", P[num].number);
num = P[num].pro;
}
printf("\n");
}
return 0;
}
改进:增加头结点和尾结点
#include<cstdio>
#include<queue>
const int MAX = 300005;
struct Node{
int number;
int pre; //之前的结点
int pro; //之后的节点
};
struct Node P[MAX];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
{
P[i].number = i;
P[i].pre = i - 1;
P[i].pro = i + 1;
}
P[0].number = 0;
P[0].pre = 0;
P[0].pro = 1;
P[n + 1].number = n + 1;
P[n + 1].pre = n;
P[n + 1].pro = n + 1;
for (int i = 0; i < m; i++)
{
int a, b, c;
int pre, pro;
scanf("%d", &a);
switch(a)
{
case 1:
scanf("%d", &b);
P[P[b].pre].pro = P[b].pro;
P[P[b].pro].pre = P[b].pre;
P[b].pre = 0;
P[b].pro = P[0].pro;
P[P[0].pro].pre = b;
P[0].pro = b;
break;
case 2:
scanf("%d", &b);
P[P[b].pre].pro = P[b].pro;
P[P[b].pro].pre = P[b].pre;
P[b].pre = P[n + 1].pre;
P[b].pro = n + 1;
P[P[n + 1].pre].pro = b;
P[n + 1].pre = b;
break;
case 3:
scanf("%d %d", &b, &c);
P[P[b].pre].pro = P[b].pro;
P[P[b].pro].pre = P[b].pre;
P[b].pre = c;
P[b].pro = P[c].pro;
P[P[c].pro].pre = b;
P[c].pro = b;
break;
}
}
int num = P[0].pro;
for (int i = 0; i < n; i++)
{
printf("%d ", P[num].number);
num = P[num].pro;
}
printf("\n");
}
return 0;
}