V: 小M的移动硬盘

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;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值