zoukankan      html  css  js  c++  java
  • [luogu p1160] 队列安排

    传送门

    题面

    题目描述

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

    1. 先将(1)号同学安排进队列,这时队列中只有他一个人;
    2. (2-N)号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为(1sim (i -1))中某位同学(即之前已经入列的同学)的左边或右边;
    3. 从队列中去掉(M(M<N))个同学,其他同学位置顺序不变。

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

    输入输出格式

    输入格式

    (1)行为一个正整数(N),表示了有(N)个同学。

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

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

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

    输出格式

    (1)行,包含最多(N)个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。

    输入输出样例

    输入样例 #1

    4
    1 0
    2 1
    1 0
    2
    3
    3
    

    输出样例 #1

    2 4 1
    
    

    说明

    样例解释: 将同学(2)插入至同学(1)左边,此时队列为:
    (2 1)
    将同学(3)插入至同学(2)右边,此时队列为:
    (2 3 1)
    将同学(4)插入至同学(1)左边,此时队列为:
    (2 3 4 1)
    将同学(3)从队列中移出,此时队列为: (2 4 1)
    同学(3)已经不在队列中,忽略最后一条指令
    最终队列:
    (2 4 1)

    数据范围

    对于(20\%)的数据,有(N≤10)
    对于(40\%)的数据,有(N≤1000)
    对于(100\%)的数据,有(N, M≤100000)

    分析

    这道题啊,赤裸裸的链表。我们直接实现一个双向链表就好了。这里使用数组实现双向链表。

    我们先定义一个node节点:

    struct node {
        int l, r;
    }l[100005];
    

    然后初始化这个链表。

    void InitList(int n) {
        for(int i = 1; i <= n; i++)
            l[i].l = l[i].r = -1;//全部初始化为-1
        l[0].r = 1;//因为一开始就有编号为1的同学
        l[1].l = 0;
        return ;
    }
    

    可以看到,我们把下标为0作为双向链表的开始。这可以避免一些问题。
    接下来定义addLeft函数,在pos位置的左边添加数x。这就是双向链表的板子了,具体见注释。

    void addLeft(int x, int pos) {
        l[x].r = pos;//节点x的右边设为pos
        l[x].l = l[pos].l;//节点x的左边是pos位置节点的左边节点
        l[l[pos].l].r = x;//pos的左边节点的右边节点应该是x
        l[pos].l = x;//pos的左边是x
        return ;
    }
    

    addRight函数同理。

    void addRight(int x, int pos) {
        l[x].l = pos;
        l[x].r = l[pos].r;
        l[l[pos].r].l = x;
        l[pos].r = x;
        return ;
    }
    

    那么怎么删除呢?很简单,我们将要删除的节点x的两边都设为-1,然后原来两边的节点中,左边的和右边的跳过节点x直接link together

    void DeleteNode(int x) {
        if(l[x].l != -1) {
            l[l[x].l].r = l[x].r;
            l[l[x].r].l = l[x].l;
            //Link together
            l[x].l = -1;
            l[x].r = -1;
            //delete node x
        }
        return ;
    }
    

    最后是遍历。由于我们是从下标为0开始的,从0开始遍历当前节点的右节点就好了,一直到-1

    void printList() {
        int x = l[0].r;
        printf("%d ",x);
        while(l[x].r != -1) {
            x = l[x].r;
            printf("%d ", x);
        }
        return ;
    }
    

    完整代码如下:

    代码

    /*
     * @Author: crab-in-the-northeast 
     * @Date: 2020-03-07 10:37:45 
     * @Last Modified by: crab-in-the-northeast
     * @Last Modified time: 2020-03-07 12:16:14
     */
    #include <iostream>
    #include <cstdio>
    
    struct node {
        int l, r;
    }l[100005];
    
    void InitList(int n) {
        for(int i = 1; i <= n; i++)
            l[i].l = l[i].r = -1;
        l[0].r = 1;
        l[1].l = 0;
        return ;
    }
    
    void addLeft(int x, int pos) {
        l[x].r = pos;
        l[x].l = l[pos].l;
        l[l[pos].l].r = x;
        l[pos].l = x;
        return ;
    }
    
    void addRight(int x, int pos) {
        l[x].l = pos;
        l[x].r = l[pos].r;
        l[l[pos].r].l = x;
        l[pos].r = x;
        return ;
    }
    
    void DeleteNode(int x) {
        if(l[x].l != -1) {
            l[l[x].l].r = l[x].r;
            l[l[x].r].l = l[x].l;
            l[x].l = -1;
            l[x].r = -1;
        }
        return ;
    }
    
    void printList() {
        int x = l[0].r;
        printf("%d ",x);
        while(l[x].r != -1) {
            x = l[x].r;
            printf("%d ", x);
        }
        return ;
    }
    
    int main() {
        int n;
        scanf("%d",&n);
        InitList(n);
    
        for(int i = 2; i <= n; i++) {
            int pos, dir;
            scanf("%d %d",&pos, &dir);
            if(dir) addRight(i, pos);
            else addLeft(i, pos);
        }
    
        int m;
        scanf("%d",&m);
        for(int i = 1; i <= m; i++) {
            int x;
            scanf("%d",&x);
            DeleteNode(x);
        }
        printList();
        return 0;
    }
    

    评测结果

    AC 100R31453533

  • 相关阅读:
    Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
    Combine 框架,从0到1 —— 4.在 Combine 中使用通知
    Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
    Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
    使用 Swift Package Manager 集成依赖库
    iOS 高效灵活地配置可复用视图组件的主题
    构建个人博客网站(基于Python Flask)
    Swift dynamic关键字
    Swift @objcMembers
    仅用递归函数操作逆序一个栈(Swift 4)
  • 原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1160.html
Copyright © 2011-2022 走看看