2019-06-04
题目:洛谷 P1160 队列安排 : https://www.luogu.org/problemnew/show/P1160
题目描述
一个学校里老师要将班上NNN个同学排成一列,同学被编号为1∼N1\sim N1∼N,他采取如下的方法:
-
先将111号同学安排进队列,这时队列中只有他一个人;
-
2−N2-N2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1∼(i−1)1\sim (i -1)1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
-
从队列中去掉M(M<N)M(M<N)M(M<N)个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入输出格式
输入格式:第111行为一个正整数NNN,表示了有NNN个同学。
第2−N2-N2−N行,第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个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
输入输出样例
4 1 0 2 1 1 0 2 3 3
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≤10N≤10;
对于40%40\%40%的数据,有N≤1000N≤1000N≤1000;
对于100%100\%100%的数据,有N,M≤100000N, M≤100000N,M≤100000。
考虑到本题要求大量的插入与删除操作,所以使用 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('\n'); 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('\n'); 50 return 0; 51 } 52 //