洛谷 P1160 队列安排

2019-06-04

题目:洛谷 P1160 队列安排 : https://www.luogu.org/problemnew/show/P1160


题目描述

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

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

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

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

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

输入输出格式

输入格式:

111行为一个正整数NNN,表示了有NNN个同学。

2−N2-N2N行,第iii行包含两个整数k,pk,pk,p,其中kkk为小于iii的正整数,ppp为000或者111。若ppp为000,则表示将iii号同学插入到kkk号同学的左边,ppp为111则表示插入到右边。

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

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

输出格式:

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

输入输出样例

输入样例#1:
4
1 0
2 1
1 0
2
3
3
输出样例#1:
2 4 1

说明

样例解释:

将同学222插入至同学111左边,此时队列为:

212 121

将同学333插入至同学222右边,此时队列为:

2312 3 1231

将同学444插入至同学111左边,此时队列为:

23412 3 4 12341

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

2412 4 1241

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

最终队列:

2412 4 1241

数据范围

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

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

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


考虑到本题要求大量的插入与删除操作,所以使用 std::list<Type>实现。

插入到***的右侧使用 $.inster<iterator $$,val>,$$指向**

插入到***的左侧使用 $.inster<++iterator $$,val>,$$指向**

list中的成员函数(与本题相关):

$.push_front(val)----在队首添加元素值为val,返回一个迭代器指向新元素    $.pop_front()----删除队首元素

$.push_back(val)----在队尾添加元素值为val,返回一个迭代器指向新元素    $.pop_back()----删除队尾元素

$.front()----获取队首元素    $.back()----获取队尾元素

$.insert(iterator,val)----在iterator指向元素的前方添加元素值为val,返回一个迭代器指向新元素

$.erase(iterator)----删除iterator指向元素

$.empty()----判断队是否为空,为空则返回true

$.remove(iterator)----删除iteartor指向元素(注意与vector等容器的remove区分)

$.remove(val)----删除队中值为val的所有元素

声明一个std::list<Type>类型的迭代器:list<ll>::iterator it;

用一个数组存储所有迭代器。

按照题意可得代码:

 1 //
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 typedef long long ll;
 5 #define ri register ll
 6 
 7 ll n,m;
 8 list<ll> q;
 9 list<ll>::iterator pos[100005];
10 
11 signed main()
12 {
13     ios::sync_with_stdio(0),cin.tie(0);
14     cin>>n;
15     q.push_back(1);
16     pos[1]=q.begin();
17     for(ri i=2;i<=n;i++)
18     {
19         ri k,p;
20         cin>>k>>p;
21         if(p==0)
22         {
23             pos[i]=q.insert(pos[k],i);
24         }
25         if(p==1)
26         {
27             list<ll>::iterator a=pos[k];
28             pos[i]=q.insert(++a,i);
29         }
30     }
31     cin>>m;
32     for(ri i=1;i<=m;i++)
33     {
34         ri x;
35         cin>>x;
36         q.remove(x);
37     }
38     while(!q.empty())
39     {
40         cout<<q.front()<<" ";
41         q.pop_front();
42     }
43     putchar('
');
44     return 0;
45 }
46 //

但要注意这时只能得40分,有三个测试点TLE

因为$.remove(val)需要占用大量时间,所以增加一个bool数组判断

 1 //
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 typedef long long ll;
 5 #define ri register ll
 6 
 7 ll n,m;
 8 list<ll> q;
 9 list<ll>::iterator pos[100005];
10 bool vis[100005];
11 
12 signed main()
13 {
14     ios::sync_with_stdio(0),cin.tie(0);
15     cin>>n;
16     q.push_back(1);
17     pos[1]=q.begin();
18     for(ri i=2;i<=n;i++)
19     {
20         ri k,p;
21         cin>>k>>p;
22         if(p==0)
23         {
24             pos[i]=q.insert(pos[k],i);
25         }
26         if(p==1)
27         {
28             list<ll>::iterator a=pos[k];
29             pos[i]=q.insert(++a,i);
30         }
31     }
32     cin>>m;
33     for(ri i=1;i<=m;i++)
34     {
35         ri x;
36         cin>>x;
37         if(!vis[x])
38         {
39             q.erase(pos[x]);
40             vis[x]=1;
41         }
42         //q.remove(x);
43     }
44     while(!q.empty())
45     {
46         cout<<q.front()<<" ";
47         q.pop_front();
48     }
49     putchar('
');
50     return 0;
51 }
52 //
原文地址:https://www.cnblogs.com/Vty66CCFF/p/10973183.html