当蒟蒻停止思考的时候那么所有题都会变的很难,一开始写数组,想了一下不行删了(T飞),
然后用f[i]=j来代表他的位置,但是删了右边的所有人的位置都要变,也不行(居然还是没想起什么是链表)
苦思冥想了半小时之后终于发现是一个很简单的双向链表Orz
AC代码(链表)
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
int k,p,x,n,m,t;
list<int>l;
bitset<MAXN>erase;
list<int>::iterator pos[MAXN];
int main(){
l.push_back(1);
pos[1]=l.begin();
scanf("%d",&n);
for(int i=2;i<=n;i++){
scanf("%d %d",&k,&p);
if(p==0){//把i插到k同学左边
pos[i]=l.insert(pos[k],i);
}else{//把i插到k同学右边
auto nextpos=next(pos[k]);
pos[i]=l.insert(nextpos,i);
}
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&x);
erase[x]=true;
}
for(auto i:l)if(!erase[i])cout<<i<<" ";
return 0;
}
观赏了一下题解之后发现这道题只有左边或者右边才能插入同学(所以是一个二叉树)中序遍历就能AC..本蒟蒻很不服气也想试试
没想到真过了
AC代码(二叉树)
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
int n,k,p,m,x;
pair<int,int>t[MAXN];
bitset<MAXN>erase;
void travel(int i){
if(t[i].first)travel(t[i].first);
if(!erase[i])cout<<i<<" ";
if(t[i].second)travel(t[i].second);
}
int main(){
scanf("%d",&n);
for(int i=2;i<=n;i++){
scanf("%d %d",&k,&p);
if(p==0)//已经有了左儿子,老儿子变成新儿子的左儿子<根k,老儿子t[k].first,新儿子i>
if(!t[k].first)t[k].first=i;
else t[i].first=t[k].first,t[k].first=i;
else//右儿子同理
if(!t[k].second)t[k].second=i;
else t[i].second=t[k].second,t[k].second=i;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d",&x),erase[x]=true;
travel(1);
return 0;
}
二叉树的比链表的快了将近50%,内存少了将近80%.....?