原题 https://www.luogu.org/problemnew/show/P1160
频繁的插入和删除就用链表,数组可以实现随机存取,链表不能
题解
方法一:数组解法
#include<bits/stdc++.h>
using namespace std;
int n,a,b,k,v[100000]={0};
struct student{
int l,r;
}d[100000];
int main()
{
cin>>n;
d[0].r=1;d[1].l=0;
for(int i=2;i<=n;i++){
cin>>a>>b;
if(b)
{ d[d[a].r].l=i;
d[i].r=d[a].r;
d[i].l=a;
d[a].r=i;//一定要放在后面
}
else{
d[d[a].l].r=i;
d[i].l=d[a].l;
d[a].l=i;
d[i].r=a;//一定要放在后面
}
}
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a;
if(v[a]==1) continue;
v[a]=1;
d[d[a].l].r=d[a].r;
d[d[a].r].l=d[a].l;
}
for(int i=0;d[i].r;i=d[i].r)//技巧
{
cout<<d[i].r<<' ';
}
return 0;
}
方法二:指针解法
#include<bits/stdc++.h>
using namespace std;
struct node{
int n;
node *left,*right;
node(int t){//利用构造函数赋初值
left=right=NULL;
n=t;//n存储的是序号
}
}*p[100010],*q;
int main()
{
int m,n,i,j,k,u=1,v;
p[1]=new node(1);
cin>>n;
for(i=2;i<=n;i++){//插入
cin>>j>>k;
p[i]=new node(i);
if(k){
if(p[j]->right){//右边有元素,需要移动
p[j]->right->left=p[i];
p[i]->right=p[j]->right;
}
p[j]->right=p[i];p[i]->left=p[j];
}
else{
if(p[j]->left)
{
p[j]->left->right=p[i];
p[i]->left=p[j]->left;
}
p[j]->left=p[i];p[i]->right=p[j];
if(j==u) u=i;//用u来记录开头元素,仅限于左插的情况,
//插在头元素左侧,从而产生了新的开头
//可以认为是没有设置头元素的弊端,数组解法设置了头元素,没有这种问题
}
}
cin>>m;
for(i=1;i<=m;i++){//删除
cin>>k;//左侧有元素
if(p[k]->left) p[k]->left->right=p[k]->right;
if(p[k]->right){//右侧有元素
p[k]->right->left=p[k]->left;
//if(k==u) u=p[k]->right->n;//u标记开头元素,可以放在下面
}
if(k==u) u=p[k]->right->n;
//***是否可以去掉
p[k]->left=p[k]->right=NULL;//注意所删元素在两头的情况
}
q=p[u];
while(q){
printf("%d ",q->n);
q=q->right;
}
return 0;
}
方法三:二叉树遍历解法
二叉树的中序遍历就是链表的顺序
#include<bits/stdc++.h>
using namespace std;
struct lol{
int lc,rc,v;
} d[101000];
void dfs(int x)//中序遍历
{
if(x==-1) return;//设置返回条件
dfs(d[x].lc);//左
if(d[x].v==0) printf("%d ",x);//根
dfs(d[x].rc);//右
}
int main()
{
int n,m;
cin>>n;
d[1].v=0;d[1].lc=d[1].rc=-1;//初始化
for(int i=2;i<=n;i++)//利用静态表建树
{
int x,y;
cin>>x>>y;
d[i].lc=d[i].rc=-1;d[i].v=0;
if(y==0)//插在左边
{
if(d[x].lc!=0)
{//砍断左子树,插入节点
d[i].lc=d[x].lc;d[x].lc=i;
}
else d[x].lc=i;
}
else
{//砍断右子树,插入节点
if(d[x].rc!=0)
{
d[i].rc=d[x].rc;d[x].rc=i;
}
else d[x].rc=i;
}
}
cin>>m;
for(int i=1;i<=m;i++)
{
int x;cin>>x;d[x].v=1;//结构体中的v标记是否删除节点
}
dfs(1);//调用中序遍历输出
}