• 【洛谷 P1160】队列安排 题解(链表+模拟)


    队列安排

    题目描述

    一个学校里老师要将班上 N N N 个同学排成一列,同学被编号为 1 ∼ N 1\sim N 1N,他采取如下的方法:

    1. 先将 1 1 1 号同学安排进队列,这时队列中只有他一个人;

    2. 2 ∼ N 2\sim N 2N 号同学依次入列,编号为 i i i 的同学入列方式为:老师指定编号为 i i i 的同学站在编号为 1 ∼ ( i − 1 ) 1\sim(i-1) 1(i1) 中某位同学(即之前已经入列的同学)的左边或右边;

    3. 从队列中去掉 M M M 个同学,其他同学位置顺序不变。

    在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

    输入格式

    第一行一个整数 N N N,表示了有 N N N 个同学。

    2 ∼ N 2\sim N 2N 行,第 i i i 行包含两个整数 k , p k,p k,p,其中 k k k 为小于 i i i 的正整数, p p p 0 0 0 或者 1 1 1。若 p p p 0 0 0,则表示将 i i i 号同学插入到 k k k 号同学的左边, p p p 1 1 1 则表示插入到右边。

    N + 1 N+1 N+1 行为一个整数 M M M,表示去掉的同学数目。

    接下来 M M M 行,每行一个正整数 x x x,表示将 x x x 号同学从队列中移去,如果 x x x 号同学已经不在队列中则忽略这一条指令。

    输出格式

    一行,包含最多 N N N 个空格隔开的整数,表示了队列从左到右所有同学的编号。

    样例 #1

    样例输入 #1

    4
    1 0
    2 1
    1 0
    2
    3
    3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    样例输出 #1

    2 4 1
    
    • 1

    提示

    【样例解释】

    将同学 2 2 2 插入至同学 1 1 1 左边,此时队列为:

    2 1

    将同学 3 3 3 插入至同学 2 2 2 右边,此时队列为:

    2 3 1

    将同学 4 4 4 插入至同学 1 1 1 左边,此时队列为:

    2 3 4 1

    将同学 3 3 3 从队列中移出,此时队列为:

    2 4 1

    同学 3 3 3 已经不在队列中,忽略最后一条指令

    最终队列:

    2 4 1

    【数据范围】

    对于 20 % 20\% 20% 的数据, 1 ≤ N ≤ 10 1\leq N\leq 10 1N10

    对于 40 % 40\% 40% 的数据, 1 ≤ N ≤ 1000 1\leq N\leq 1000 1N1000

    对于 100 % 100\% 100% 的数据, 1 < M ≤ N ≤ 1 0 5 11<MN105


    思路

    使用 list 类型的双向链表 li 来表示队列。使用 pos 数组记录每个数在链表中的位置,方便后续的删除操作。使用 bitset 类型的 vis 数组记录每个数是否已经被删除。

    首先,将数字 1 加入队列,并将其位置记录到 pos[1] 中。然后逐个读入操作,根据插入的方向,在指向位置的前或后插入对应的数字,并将其位置记录到 pos 数组中。

    接着,读入需要删除的数字,对于已经删除过的数字直接跳过,否则在链表中删除对应的节点,并将 vis 数组中对应的位置设为 1。

    最后,遍历链表输出剩下的数字即可。


    AC代码

    #include 
    #include 
    #include 
    #define AUTHOR "HEX9CF"
    using namespace std;
    
    const int N = 1e5 + 5;
    
    int n, m;
    list<int> li;
    list<int>::iterator pos[N], it;
    bitset<N> vis;
    
    void read(int &x)
    {
        char ch;
        x = 0;
        while (!('0' <= ch && ch <= '9'))
        {
            ch = getchar();
        }
        while (('0' <= ch && ch <= '9'))
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
    }
    
    int main()
    {
        read(n);
        li.push_back(1);
        pos[1] = li.begin();
        for (int i = 2; i <= n; i++)
        {
            int k, p;
            read(k);
            read(p);
            it = pos[k];
            if (p)
            {
                // 插到右边
                it++;
            }
            pos[i] = li.insert(it, i);
        }
    
        vis.reset();
        read(m);
        for (int i = 0; i < m; i++)
        {
            int x;
            read(x);
            if (vis[x])
            {
                continue;
            }
            li.erase(pos[x]);
            vis[x] = 1;
        }
    
        for (const auto &x : li)
        {
            cout << x << " ";
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
  • 相关阅读:
    Unity UGUI开发规范
    计算机算法分析与设计(20)---回溯法(0-1背包问题)
    论文阅读: 面向Planning的端到端智驾Planning-oriented Autonomous Driving
    Vue前端框架
    alsa pcm接口之pcm设备的状态STATE
    书剑宠物疫苗接种管理软件操作教程
    LVGL---对象(lv_obj_t)
    基于SSM的超市管理系统
    lingo记录
    PHP毕业设计源代码高校兼职应聘招聘系统-前台Uniapp
  • 原文地址:https://blog.csdn.net/qq_34988204/article/details/133466963