https://www.luogu.com.cn/problem/P1160
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define ci const int &//优化加速 #define guo_fu_han_xin return #define luan_sha_ni 0 using namespace std; const int N=100005; int n,m; struct node *nd[N],*rt;//先定义,这样就可以在结构体中用 struct node{ int number; node *pre,*nxt; node(ci Number=0):number(Number){pre=nxt=NULL;}//初始化(初始化为0?) inline void insert0(ci u){ node *now=new node(u); nd[u]=now;//编号为u的结点存进来 if(rt==this) rt=now;//真就直接this if(pre) pre->nxt=now;//如果前面的指针不为空(不是开头),那么前面的指针应该指到新插入的结点上 now->pre=pre;//新插入的结点指向前面的结点 now->nxt=this;//在this前面插入,所以nxt指向this pre=now;//this的pre指向now }//前插 inline void insert1(ci u){ node *now=new node(u); nd[u]=now; if(nxt) nxt->pre=now;//如果不是结尾,那么下一个结点的前面应该是插入的结点 now->pre=this;//后插,所以是插入的结点前面指向被后插的结点 now->nxt=nxt;//插入的结点指向本来的后面的结点 nxt=now;//被后插的结点的下一个指向当前插入的结点 } inline void remove(){ if(!pre) rt=nxt;//如果最前面的结点被删除,那么最前面的结点应更新为原本的结点的下一个结点 if(pre) pre->nxt=nxt;//如果不在开头 if(nxt) nxt->pre=pre;//如果不在结尾 nd[number]=NULL;//被删除之后指针指向NULL } }; int main() { scanf("%d",&n); nd[1]=new node(1); rt=nd[1]; for(int i=2;i<=n;i++){ int x,o; scanf("%d%d",&x,&o); if(o==0){ nd[x]->insert0(i); } else{ nd[x]->insert1(i); } } scanf("%d",&m); for(int i=1;i<=m;i++){ int x; scanf("%d",&x); if(nd[x]) nd[x]->remove(); } while(rt){ printf("%d ",rt->number); rt=rt->nxt;//不断向后输出 } guo_fu_han_xin luan_sha_ni; }
题目描述
一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:
-
先将1号同学安排进队列,这时队列中只有他一个人;
-
2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;
-
从队列中去掉M(M<N)个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入格式
第1行为一个正整数N,表示了有N个同学。
第2−N行,第i行包含两个整数k,p,其中k为小于i的正整数,p为0或者1。若p为0,则表示将i号同学插入到k号同学的左边,p为1则表示插入到右边。
第N+1行为一个正整数M,表示去掉的同学数目。
接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。
输出格式
1行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
输入输出样例
说明/提示
样例解释:
将同学2插入至同学1左边,此时队列为:
21
将同学3插入至同学2右边,此时队列为:
231
将同学4插入至同学1左边,此时队列为:
2341
将同学3从队列中移出,此时队列为:
241
同学3已经不在队列中,忽略最后一条指令
最终队列:
241
数据范围
对于20%的数据,有N≤10;
对于40%的数据,有N≤1000;
对于100%的数据,有N,M≤100000。