题面:
样例输入#1:
4
1 0
2 1
1 0
2
3
3
样例输出#1:
2 4 1
解题:
思路1:暴力!
用一维数组储存,每读入/删除一个元素,则将其后面的全部元素后移/前移一个单位
NO NO NO!时间复杂度O(N*(M+N))≈O(N²),
对于数据范围:N≤,不容乐观……
思路2:双向链表!
创建一个同学类D,其拥有成员变量:
public:
int id; //自身数字
int nx = 0; //next 后一个元素
int bf = 0; //before 前一个元素
这样,我们便可以随时找到他的上一个、下一个同学
如下图所示:我们在2、1之间建立了链接,
能访问到上一个、下一个元素,便是双向链表的特点
接下来,我们模拟样例中3号同学入队的过程:
可见:我们只需要更改2的next、1的before元素,并将3链接2、1即可;
而删除则是置入的逆过程
即:取消链接、恢复前后元素本来的链接即可。
最后,我们从链表头开始遍历,以此找其后续的next元素,遍历至尾部(即next=0)即停止;
❀❀❀❀❀❀❀完结撒花❀❀❀❀❀❀❀
AC代码奉上
#include<iostream>
#include<algorithm>
#include<vector>
#define MAXN int (1e6+5)
using namespace std;
class D; //先声明一下
int n, m, head = 1, a[MAXN], d[MAXN] = { 0 };
vector<D>v; //储存同学们的容器
class D
{
public:
int id; //自身数字
int nx = 0; //next 后一个元素
int bf = 0; //before 前一个元素
D(){}
D(int id, int k, int type) //id:编号 k:与题目输入一致 type:区分左侧/右侧
{
this->id = id;
if (k == 0)return;
switch(type)
{
case 0: //置入左侧
this->nx = k;
this->bf = v[k].bf;
v[v[k].bf].nx = id;
v[k].bf = id;
if (this->bf == 0)head = id; //如果before为0,则更新队首为新元素
break;
case 1: //置入右侧
this->bf = k;
this->nx = v[k].nx;
v[v[k].nx].bf = id;
v[k].nx = id;
break;
}
}
};
void del(int k) //删除k同学
{
int t_bf = v[k].bf;
int t_nx = v[k].nx;
v[t_bf].nx = t_nx;
v[t_nx].bf = t_bf;
}
int main()
{
v.push_back(D()); //占据0位置
v.push_back(D(1, 0, 520)); //首个同学
cin >> n;
for (int i = 2; i <= n; i++)
{
int k, p;
cin >> k >> p;
v.push_back(D(i, k, p));
}
cin >> m;
for (int i = 1; i <= m; i++)
{
int k; cin >> k;
if (d[k])continue; //已经被删除过了,直接跳过
del(k);
d[k] = 1;
}
int pos;
for (pos = head; v[pos].nx != 0; )
{
cout << v[pos].id << " ";
pos = v[pos].nx;
}
cout << v[pos].id << endl;
return 0;
}