#include using namespace std; //双链表模板 const int N = 100010; int e[N]; //数据 int l[N]; //左链表 int r[N]; //右链表 int idx; //准备放入的索引值 //正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。 //正是因为有了这句话,如果没有删除的标识了,真的有重复指令就会让数据出问题。 // 因为可能重复的对左右结点进行操作,造成数据错误。 int st[N]; //删除标识 // 黄海写的题解 // https://www.acwing.com/solution/content/35794/ //0表示头,1表示尾,正式使用的是从idx=2开始 void init() { //0的右端是1,1的左端是0 r[0] = 1, l[1] = 0, idx = 2; } //函数含义:在k号节点右侧插入,值为x //如果想实现:在k号节点左侧插入,值为x 则调用:add(l[k],x),意义为在k的左侧, //相当于在k的左侧节点的右侧, void add(int k, int x) { e[idx] = x; //将x放入到一个空的单元格中 l[idx] = k; //将新增加的单元格的右指针指向k的下一链路节点 r[idx] = r[k]; //将新增加的单元格的左指针指向k //完成上面两步后,只是让idx这个节点建立了与原来两个节点的关系,而原来的两个k与r[k], // l[r[k]]还是旧的值,也需要进行修改。 l[r[k]] = idx; r[k] = idx; //为下一次做准备 idx++; } //删除第k个节点 void remove(int k) { r[l[k]] = r[k]; l[r[k]] = l[k]; } int n, K, p, m, x; //输出双链表 void print() { //遍历双向链表的方法 for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << " "; cout << endl; } int main() { //初始化双链表 init(); //读入 cin >> n; //先将1号同学安排进队列 //最左端就是表示在head(0号)的右侧插入一个数据 add(0, 1); for (int i = 2; i <= n; i++) { //k为小于i的正整数 cin >> k >> p; //p为0,表示将i号同学插入到k号同学的左边 //p为1,表示将i号同学插入到k号同学的右边 //idx从2开始,所以下标需要k+1传入才对 //就是1号同学的idx=2 //就是2号同学的idx=3 //就是3号同学的idx=4 //就是k号同学的idx=k+1 //右边就是正常的add(k+1,i) //左边稍有一点变化:add(l[k+1],i), 表示在当前号的左侧那个,就是它的前面结点的右侧放入 if (p == 0) add(l[k + 1], i); else add(k + 1, i); } //表示去掉的同学数目 cin >> m; for (int i = 1; i <= m; i++) { cin >> x; //表示将x号同学从队列中移去 if (!st[x + 1]) { remove(x + 1); st[x + 1] = 1; } } //输出链表 (表示了队列从左到右所有同学的编号,行末换行且无空格) print(); return 0; }