双向链表
//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;
}