题目描述
一个学校里老师要将班上NN个同学排成一列,同学被编号为1\sim N1∼N,他采取如下的方法:
先将1号同学安排进队列,这时队列中只有他一个人;
2-N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
从队列中去掉M(M<N)个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入格式
第1行为一个正整数N,表示了有N个同学。
第2-N行,第i行包含两个整数k,p,其中k为小于i的正整数,p为0或者1。若p为0,则表示将i号同学插入到kk号同学的左边,p为1则表示插入到右边。
第N+1行为一个正整数M,表示去掉的同学数目。
接下来MM行,每行一个正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。
输出格式
1行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
输入输出样例
输入 #1
4
1 0
2 1
1 0
2
3
3
输出 #1
2 4 1
说明/提示
样例解释
数据范围
思路:
没用什么技巧,就是单纯的链表插入和删除,模拟一遍。代码稍稍有点长
ps:这个题没有删除后只剩一个人这种情况的测试点,我觉得应该有这种情况,有的话还得加一点点代码(下面代码没加),这种情况倒不是很难。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100050;
struct node{ //前驱,后继
int front,rear;
}stu[maxn];
int n,k,p,m,x,now;
int main()
{
cin>>n;
stu[1].front = stu[1].rear = -1; //初始化前驱后继都为-1
for(int i=2;i<=n;i++) //插入部分
{
stu[i].front = stu[i].rear = -1; 初始化前驱后继都为-1
cin>>k>>p;
if(p==0) //i插入到k的左侧
{
if(stu[k].front==-1) //k是第一个
{
stu[k].front=i;
stu[i].rear=k;
}
else if(stu[k].front>-1) //k不是第一个
{
stu[stu[k].front].rear=i;
stu[i].front=stu[k].front;
stu[k].front=i;
stu[i].rear=k;
}
}
else if(p==1)//i插入到k的右侧
{
if(stu[k].rear==-1) //k是最后一个
{
stu[k].rear=i;
stu[i].front=k;
}
else if(stu[k].rear>-1) //k不是最后一个
{
stu[stu[k].rear].front=i;
stu[i].rear=stu[k].rear;
stu[k].rear=i;
stu[i].front=k;
}
}
}
cin>>m; //删除部分
for(int i=0;i<m;i++)
{
cin>>x;
if(stu[x].rear==-1) //x是最后一个
{
stu[stu[x].front].rear=-1;
stu[x].front=-1;
}
else if(stu[x].rear!=-1) //x不是最后一个
{
stu[stu[x].front].rear = stu[x].rear;
stu[stu[x].rear].front = stu[x].front;
stu[x].front=stu[x].rear=-1;
}
else if(stu[x].front==-1) //x是第一个
{
stu[stu[x].rear].front=-1;
stu[x].rear=-1;
}
}
for(int i=1;i<=n;i++) //寻找队首
{
if(stu[i].front==-1 && stu[i].rear!=-1) //队首的特征
{
now=i;
break;
}
}
cout<<now; //不断找后继,直到最后一个(特点为rear=-1)
while(stu[now].rear!=-1)
{
cout<<" "<<stu[now].rear;
now=stu[now].rear;
}
return 0;
}