洛谷P1160 队列安排

洛谷 P1160 队列安排

题目描述

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

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

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

输入格式

第11行为一个正整数NN,表示了有NN个同学。

第2-N2−N行,第ii行包含两个整数k,pk,p,其中kk为小于ii的正整数,pp为00或者11。若pp为00,则表示将ii号同学插入到kk号同学的左边,pp为11则表示插入到右边。

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

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

输出格式

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

输入输出样例

输入 #1复制

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

输出 #1复制

1
2 4 1

说明/提示

样例解释:

将同学22插入至同学11左边,此时队列为:

2 121

将同学33插入至同学22右边,此时队列为:

2 3 1231

将同学44插入至同学11左边,此时队列为:

2 3 4 12341

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

2 4 1241

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

最终队列:

2 4 1241

数据范围

对于20%20%的数据,有N≤10N≤10;

对于40%40%的数据,有N≤1000N≤1000;

对于100%100%的数据,有N, M≤100000N,M≤100000。


分析

参考https://www.luogu.com.cn/blog/onlynagesha/solution-p1160

用了vector试了一下,果不其然TLE。通过题解学到了一个新的STL list。list是一个双向链表,可以在头尾插入元素。

1
2
myList.push_front(1);
myList.push_back(2);

对应的有pop_front()用于移除头部的元素,pop_back()用于移除尾部的元素。

1
2
3
4
5
typedef list<int>::iterator Iter;
Iter itBegin = myList.begin();
Iter itEnd = myList.end();
for (; itBegin != itEnd; ++itBegin)
printf(" %d", *itBegin);

这段代码演示的是list提供的,用于访问内部元素的迭代器。迭代器的类型是list::iterator(这里模板参数Tp需要与你操作的链表一致)。

迭代器的用法和指针有些像,可以用*运算符访问内部的元素,++和–运算符可以将它后移或前移一位(建议写成前置形式),用==和!=运算符进判断两个迭代器所指的位置是否一致。但要注意:list的迭代器不支持it += x或it1 - it2这样的运算,也不支持<,<=等运算符。

回到这道题上,最主要的就是要记录每个元素的位置,因为是链表,所以在插入或是删除元素后,其他的元素不会变动,所以可以直接用一个迭代器数组list<int> pos[MAXN] 来保存每个元素的位置,方便之后的插入和删除。

代码

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
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;

list<int>::iterator pos[100010];
list<int> Q;
bool erased[100010];
int N;

void buildQueue()
{
Q.push_front(1);
pos[1] = Q.begin();

for(int i = 2; i <= N; i++)
{
int k, p;
cin >> k >> p;
if(p == 0)
pos[i] = Q.insert(pos[k], i);
else if(p == 1)
{
list<int>::iterator nextIt = next(pos[k]);
pos[i] = Q.insert(nextIt, i);
}
}
int M;
cin >> M;
for(int i = 0; i < M; i++)
{
int x;
cin >> x;
if(!erased[x])
Q.erase(pos[x]);
erased[x] = true;
}

}

int main(int argc, const char * argv[])
{
ios::sync_with_stdio(false);
cin >> N;
buildQueue();

for(list<int>::iterator it = Q.begin(); it != Q.end(); it++)
cout << *it << " ";

return 0;
}

作者

Jhuoer Yen

发布于

2021-04-21

更新于

2023-09-18

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×