第一遍选择了写一个删除函数,结果WA了三个点:
#include<cstdio>
#include<iostream>
using namespace std;
inline int read(){
int x=0;
char c=getchar();
bool f=(c=='-');
while(c>57||c<48) c=getchar();
while(c<58&&c>47) x=(x<<3)+(x<<1)+(c^48),c=getchar();
return f?-x:x;
}
const int MAXN=100005;
int l[MAXN],r[MAXN];
int a,b;
void insert(int x,int k,int p){
if(p==0){
r[x]=k;
l[x]=l[k];
r[l[k]]=x;
l[k]=x;
}else if(p==1){
l[x]=k;
r[x]=r[k];
l[r[k]]=x;
r[k]=x;
}
return;
}
void del(int x){
r[l[x]]=r[x];
l[r[x]]=l[x];
return;
}
void search(int x){
if(r[0]!=x) printf(" ");
printf("%d",x);
if(r[x]==0){
printf("\n");
return;
}
search(r[x]);
}
int main(){
int n=read();
for(int i=2;i<=n;i++){
a=read();
b=read();
insert(i,a,b);
}
int m=read();
for(int i=1;i<=m;i++){
a=read();
del(a);
}
search(r[0]);
return 0;
}
然而选择对每个同学分别判重,就得到了满分:
#include<cstdio>
#include<fstream>
using namespace std;
inline int read(){
int x=0;
char c=getchar();
bool f=(c=='-');
while(c>57||c<48) c=getchar();
while(c<58&&c>47) x=(x<<3)+(x<<1)+(c^48),c=getchar();
return f?-x:x;
}
const int MAXN=100005;
int l[MAXN],r[MAXN],s[MAXN];
int a,b;
void insert(int x,int k,int p){
if(p==0){
r[x]=k;
l[x]=l[k];
r[l[k]]=x;
l[k]=x;
}else if(p==1){
l[x]=k;
r[x]=r[k];
l[r[k]]=x;
r[k]=x;
}
return;
}
void search(int x){
if(s[x]==1){
search(r[x]);
return;
}
if(x==0){
printf("\n");
return;
}
if(r[0]!=x) printf(" ");
printf("%d",x);
search(r[x]);
}
int main(){
//freopen("P1160.out","w",stdout);
int n=read();
for(int i=2;i<=n;i++){
a=read();
b=read();
insert(i,a,b);
}
int m=read();
for(int i=1;i<=m;i++){
a=read();
s[a]=1;
}
search(r[0]);
return 0;
}
经过思考,我发现输入会重复删除相同的同学。使用第一种方法时,当一位同学已经被删除过后,他的左右邻居便不会再被维护,因而后续再删除这位同学有可能导致位置的混乱。使用第二种方法则相当于跳过了后续的重复删除,因而能够通过题目。