题意
给出n个人,一开始1号站在第一位,之后给出n-1个操作,每次给出一对数a b,如果b为0那么就把人i插到人a的左边,否则插到人a的右边。后面给出m个操作,每次给出一个数,代表把这个人从队列里删掉(如果已经不在队列里就忽视),最后输出这个队列。
思路
这道题我们可以用到双向链表,然后按照题目说的做就可以了。
代码
#include<cstdio>
using namespace std;
struct node{
int l,r,v;//l,r分别代表这个人左右站的人,v代表这个人的编号(好像可以不用这样)
}s[100001];
int n,a,b,mal;//mal记录最左边的点,输出时从这开始遍历
void insl(int old,int now) {
s[s[old].l].r=now;//把now插到old的左边,那么old的左边的点的右边就会指向now
s[now].r=old;//now这个点在左边,所以右边就是old
s[now].l=s[old].l;//now的左边就是old之前的左边
s[old].l=now;//now插在old左边
if (mal==old) mal=now;//更新最左边的点
}
void insr(int old,int now) {
s[s[old].r].l=now;//把now插在右边,那old之前的右边的左边就会变成now
s[now].r=s[old].r;//now的右边指向old之前的右边
s[now].l=old;//now插在old的右边,所以now的左边是old
s[old].r=now;//old的右边就是now
}
void del(int x) {
s[s[x].l].r=s[x].r;//x删除了,所以x左边和右边的点会连起来
s[s[x].r].l=s[x].l;
if (x==mal) mal=s[x].r;
s[x].l=s[x].r=0;s[x].v=-1;
}
int main() {
scanf("%d",&n);
s[1].v=1;
mal=1;
for (int i=2;i<=n;i++) {
scanf("%d%d",&a,&b);
s[i].v=i;
if (!b) insl(a,i);//插入左边
else insr(a,i);//插入右边
}
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%d",&a);
if (s[a].v<0) continue;//已经不在了就可以忽视
del(a);//删除
}
for (;s[mal].v;mal=s[mal].r)//遍历链表输出
printf("%d ",s[mal].v);
return 0;
}