P1160 队列安排

题目链接

题目描述

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

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

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

输入格式

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

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

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

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

输出格式

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

题解

使用双向链表模拟即可,注意不要写 ub

代码

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
#include <iostream>
using namespace std;
struct d {
int l, r;
} a[100010];
int v[100010];
int n, m;
int k, p;
int main() {
cin >> n;
a[1].l = 0, a[1].r = 100009, a[0].r = 1;
for (int i = 2; i <= n; i++) {
cin >> k >> p;
if (p == 0)
a[i].l = a[k].l, a[i].r = k, a[a[k].l].r = i, a[k].l = i;
else
a[i].r = a[k].r, a[i].l = k, a[a[k].r].l = i, a[k].r = i;
}
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> k;
if (!v[k])
a[a[k].l].r = a[k].r, a[a[k].r].l = a[k].l, v[k] = true;
}
int bib = 0;
for (int i = 1; i <= n; i++) {
bib = a[bib].r;
if (bib != 100009)
cout << bib << " ";
else
break;
}
return 0;
}

注意

  1. 定义链表不存在中的元素时注意数组是否会越界
文章作者: answerend42
文章链接: http://answerend42.github.io/2020/11/12/lg1160/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 answerend42的Blog