队列安排
题目描述
一个学校里老师要将班上NN个同学排成一列,同学被编号为1\sim N1∼N,他采取如下的方法:
先将11号同学安排进队列,这时队列中只有他一个人;
2-N2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1\sim (i -1)1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
从队列中去掉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
4
1 0
2 1
1 0
2
3
3
输出 #1
2 4 1
一道链表经典题目,学数据结构时都是用指针+结构体模拟链表;这里直接用二维数组模拟链表,插入和删除的主体思想还是一样的;
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int a[100010][4];//a[][1]表示本身,a[][2]表示左边的数,a[][3]表示右边的数
int main(){
int n;
scanf("%d",&n);
int k,p,s;
s=1;//开头元素
a[1][1]=1;
for(int i=2;i<=n;i++){
scanf("%d%d",&k,&p);
a[i][1]=i;
if(p==0){//左边
a[a[k][2]][3]=i,a[i][2]=a[k][2];
a[i][3]=k,a[k][2]=i;
if(k==s) s=i;
}
else{//右边
a[a[k][3]][2]=i,a[i][3]=a[k][3];
a[i][2]=k,a[k][3]=i;
}
}
int m,x;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&x);
if(a[x][1]==0) continue;
a[x][1]=0;
a[a[x][2]][3]=a[x][3];
a[a[x][3]][2]=a[x][2];
n--;//剩余几个人
if(x==s) s=a[x][3];
}
for(int i=1;i<=n;i++){
printf("%d ",a[s][1]);
s=a[s][3];
}
printf("\n");
return 0;
}