题目大意:
关键代码:
voidinsert_right(int a,int b)
head=a;
head=a;
scanf("%d",&n);
head=1;
for(i=2;i<=n;i++)
{
scanf("%d%d",&k,&l);
if(l==0)
insert_left(i,k);
else if(l==1)
insert_right(i,k);
{
scanf("%d",&k);
delet[k]=true;
if(k==head)
j=_left[head];
}
while(j!=0)
{
if(_left[j]==0)
break;
}
while(j!=0)
{
if(!delet[j])
printf("%d ",j);
j=_right[j];
}
一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:
1.先将1号同学安排进队列,这时队列中只有他一个人;
2.2~N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1~i-1中某位同学(即之前已经入列的同学)的左边或右边;
3.从队列中去掉M(M
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
1.先将1号同学安排进队列,这时队列中只有他一个人;
2.2~N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1~i-1中某位同学(即之前已经入列的同学)的左边或右边;
3.从队列中去掉M(M
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
分析:由于数据较大,(
对于100%的数据,有N,M≤100000
)所以如果只是普通的插入调整,时间会达到O(N^2+MN),所以普通的算法就不行了,我们应该用双向链表left【i】表示i左边的元素,right【i】表示j右边的元素。然后插入是只需要改变一下左右两边指针(如果不懂,可以看我的代码实现)。
{
_left[_right[b]]=a;
_right[a]=_right[b];
_right[b]=a;
_left[a]=b;
}
void insert_left(int a,intb)
{
if(b==head)
_right[_left[b]]=a;
_left[a]=_left[b];
_left[b]=a;
_right[a]=b;
}
//以上是从左添加和从右添加
整体代码:
#include
#include
#include
#include
using namespace std;
//对于100%的数据,有N, M≤100000。
int _left[100001],_right[100001];
bool delet[100001];
int n,m;
int head;
void insert_right(int a,int b)
{
_left[_right[b]]=a;
_right[a]=_right[b];
_right[b]=a;
_left[a]=b;
}
void insert_left(int a,int b)
{
if(b==head)
_right[_left[b]]=a;
_left[a]=_left[b];
_left[b]=a;
_right[a]=b;
}
int main()
{
int i,j,k,l;
}
j=head;
scanf("%d",&m);
for(i=1;i<=m;i++)
j=_left[j];
//其实我也不知道怎么会这样,一开始从left输出顺序刚好反掉,估计应该是搞反了= =
return 0;
}