洛谷p1160 双向链表

题目大意:
一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:
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右边的元素。然后插入是只需要改变一下左右两边指针(如果不懂,可以看我的代码实现)。
 关键代码:
   voidinsert_right(int a,int b)
{
_left[_right[b]]=a;
_right[a]=_right[b];
_right[b]=a;
_left[a]=b;
}

void insert_left(int a,intb)
{
if(b==head)
 head=a;
_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)
  head=a;
_right[_left[b]]=a;
_left[a]=_left[b];
_left[b]=a;
_right[a]=b;
}


int main()
{
int i,j,k,l;
      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);
j=head; 
scanf("%d",&m);
for(i=1;i<=m;i++)
  {
  scanf("%d",&k);
  delet[k]=true;
    if(k==head)
      j=_left[head];
  }
 
      while(j!=0)
        {
          if(_left[j]==0)
          break;
j=_left[j];
  }

    while(j!=0)
        {
        if(!delet[j])
          printf("%d ",j);
        j=_right[j];
  }
//其实我也不知道怎么会这样,一开始从left输出顺序刚好反掉,估计应该是搞反了= =
return 0;
}

你可能感兴趣的:(洛谷p1160 双向链表)