sicily 1934. 移动小球

//刘汝佳的《算法竞赛入门经典》P95
#include<iostream>        //双向链表,强调小球之间的相对顺序,而非绝对顺序    
using namespace std;
int l[500010],r[500010];    //l[i],r[i]分别记录编号i的小球的左边left和右边right的小球编号
void link(int x,int y)        //x,y成为邻居,即 right[x]=y;left[y]=x, x在y左边
{
    r[x]
=y;l[y]=x;
}
int main()
{
    
int t,n,m,tag,x,y;
    cin
>>t;
    
while(t--)
    {
        cin
>>n>>m;
        
for(int i=0;i<=n;++i)    //增加两个虚拟小球,编号为 0,n+1, 第一个小球的左边一直是0,最后一个小球的右边一直是n+1
            link(i,i+1);
        
while(m--)
        {
            cin
>>tag>>x>>y;
            link(l[x],r[x]);    
//删除编号x的小球,就是让x原来的左边和右边成为邻居
            if(tag==1)        //在y小球左边插入x
            {
                link(l[y],x);    
//先让编号left[y],x的小球成为邻居
                link(x,y);        //再让编号x,y的小球成为邻居,即在left[y],y中间插入 x 小球
                
//这里要注意两个语句的顺序,如果写反了则在执行 link(l[y],x) 前 l[y]的值已经改变了,即 l[y]=x;
            }
            
else
            {
                link(x,r[y]);
                link(y,x);
            }
        }
        
int p=r[0];        //第一个小球的左边是0
        while(p!=n+1)    
        {
            cout
<<p<<" ";
            p
=r[p];        //最后一个小球的右边是n+1
        }
        cout
<<endl;
    }
    
return 0;
}

  

posted on 2011-07-08 14:21  sysu_mjc  阅读(314)  评论(0编辑  收藏  举报

导航