• 洛谷 P1160 队列安排


    传送门

    我在这里

    思路

    这道题就是一道链表模板题,还是有些巧妙的啦

    因为有频繁的插入和删除操作,正好可以用链表做,这里用的是数组模拟的双向链表

    首先定义结构体,表示链表的节点,(a[x].l)表示(x)的左边这个同学的编号,(a[x].r)表示(x)的右边同学的编号

    struct node {
        int l, r;
    } a[N];
    

    下面有几个重点操作,分别是左边插入,右边插入,删除操作,以及输出

    (可能有些绕口,见谅见谅)

    1.左边插入

    两个参数表示:将(x)插入到(pos)节点的左边(因为是左边插入嘛)

    因为我们把(x)插入到了(pos)的左边,所以(x)的右边节点自然应该为(pos)节点,即(a[x].l=a[pos].r)(x)的左边节点则为原来(pos)节点的左边节点,即(a[x].l = a[pos].l),这时原本(pos)的左边节点的右边节点就变为了(x),即(a[a[pos].l].r=x),最后(pos)节点的左边节点变为了(x),即(a[pos].l=x),当然顺序是要有的,写错了就可能导致答案错误

    inline void addleft(int x, int pos) {
        a[x].r = pos;
        a[a[pos].l].r = x;
        a[x].l = a[pos].l;
        a[pos].l = x;
    }
    

    2.右边插入

    右边插入与左边插入完全相反,这里自己体会

    inline void addright(int x, int pos) {
        a[x].l = pos;
        a[a[pos].r].l = x;
        a[x].r = a[pos].r;
        a[pos].r = x;
    }
    

    3.删除操作

    那么如何删除这个节点呢??

    我们可以一开始把所有节点的左右节点都定义为(-1),表示没有左右节点,而在插入之后就有了左右节点

    我们把当前节点(pos)的左边节点的右边节点设置成(a[pos].r),即(a[a[pos].l].r = a[pos].r),把其右边节点的左边节点设置为(a[pos].l),即(a[a[pos].r].l = a[pos].l),然后删除操作就完成了一半,在遍历时就会直接跳过这个节点,然后把(pos)节点的左右节点都设置为(-1),然后就完成了删除操作

    inline void dele(int x) {
        if(a[x].l == -1) return;
        a[a[x].l].r = a[x].r;
        a[a[x].r].l = a[x].l;
        a[x].l = -1;
        a[x].r = -1;
    }
    

    4.输出

    那么如何输出呢?

    我们在一开始把(0)节点的右边节点设为(1),(1)节点的左边节点设为(0),然后在过程中这些节点的左右节点都发生了变化,但是第一个节点一定是(0)号节点的右边节点,然后循环定义(x)(x)节点的右边节点,如果不为(-1)就一直输出,这样就完成了输出操作

    inline void write() {
        int x = a[0].r;
        while(1) {
            cout << x << ' ';
            if(a[x].r == -1) break;
            x = a[x].r;
        }
    }
    

    代码

    #include <bits/stdc++.h>
    #define N 1000111
    using namespace std;
    
    struct node {
        int l, r;
    } a[N];
    
    int n, m;
    
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
        for(; isdigit(c); c = getchar()) x = x * 10 + c - 48;
        return x * f;
    }
    
    inline void addright(int x, int pos) {
        a[x].l = pos;
        a[a[pos].r].l = x;
        a[x].r = a[pos].r;
        a[pos].r = x;
    }
    
    inline void addleft(int x, int pos) {
        a[x].r = pos;
        a[a[pos].l].r = x;
        a[x].l = a[pos].l;
        a[pos].l = x;
    }
    
    inline void dele(int x) {
        if(a[x].l == -1) return;
        a[a[x].l].r = a[x].r;
        a[a[x].r].l = a[x].l;
        a[x].l = -1;
        a[x].r = -1;
    }
    
    inline void write() {
        int x = a[0].r;
        while(1) {
            cout << x << ' ';
            if(a[x].r == -1) break;
            x = a[x].r;
        }
    }
    
    int main() {
        n = read();
        int k, p;
        for(int i = 1; i <= n; i++) {
            a[i].l = a[i].r = -1;
        }
        a[1].l = 0;
        a[0].r = 1;
        for(int i = 2; i <= n; i++) {
            k = read(), p = read();
            if(p == 0) addleft(i, k);
            else addright(i, k);
        }
        m = read();
        for(int i = 1; i <= m; i++) {
            k = read();
            dele(k);
        }
        write();
        return 0;
    }
    
    
  • 相关阅读:
    CSS3嵌入web字体与布局
    Hbase 技术细节笔记(下)
    Hbase 技术细节笔记(上)
    全排列算法(递归和字典)
    一分钟掌握位运算符—与(&)、非(~)、或(|)、异或(^)
    MySQL中count函数使用方法详解
    ZAB协议与Paxos算法
    泊松分酒(穷举法)
    hadoop解决Could not locate executable nullinwinutils.exe in the Hadoop binaries.问题
    Redis系列八:redis主从复制和哨兵
  • 原文地址:https://www.cnblogs.com/loceaner/p/11098066.html
Copyright © 2020-2023  润新知