移动小球
时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte
总提交:883 测试通过:107
总提交:883 测试通过:107
描述
你有一些小球,从左到右依次编号为1,2,3,…,n,如下图所示:
你可以执行两种指令。其中A X Y表示把小球X移动到小球Y左边,B X Y表示把小球X移动到小球Y右边。指令保证合法,即X不等于Y。
例如,在初始状态下执行A 1 4后,小球1被移动到小球4的左边,如下图所示:
如果再执行B 3 5,结点3将会移到5的右边,如下图所示:
输入
输入小球个数n。指令条数m和m条指令,注意,1≤n≤500000,0≤m≤100000。
输出
从左到右输出最后的小球序列。
样例输入
6 2
A 1 4
B 3 5
样例输出
2 1 4 5 3 6
题目来源
刘汝佳《算法竞赛入门经典》
分析:很难想到的解法。也不是说没见过,就是不太容易想起来。其实类似于双链表。很nice的解法!此题坑较多= =
//移动小球
//坑真是多:getchar(别再忘了),cin超时,交换有顺序,输出要递增变化,输出最后无空格
#include<iostream>
using namespace std;
int lefts[500001];
int rights[500001];
void init(int n)
{
rights[0] = 1;
for(int i=1;i<=n;i++)
{
lefts[i] = i-1;
rights[i] = i+1;
}
}
int main()
{
int n, m, x, y;
char ch;
scanf("%d%d",&n,&m);
init(n);
//getchar();
while(m--)
{
getchar();
scanf("%c%d%d",&ch,&x,&y);
//cin>>ch>>x>>y;
lefts[rights[x]] = lefts[x]; // 调整原来x的左右
rights[lefts[x]] = rights[x];
if(ch == 'A')
{
rights[lefts[y]] = x;
lefts[x] = lefts[y];
rights[x] = y;
lefts[y] = x;
}
else
{
/*
rights[y] = x;
lefts[x] = y;
rights[x] = rights[y];
lefts[rights[y]] = x;
*/
rights[x] = rights[y]; // 顺序先后很重要!
lefts[rights[y]] = x;
rights[y] = x;
lefts[x] = y;
}
}
//for(int i=0;i<n-1;i++) printf("%d ",rights[i]);
//printf("%d\n",rights[n-1]);
int tmp = 0;
for(int i=0;i<n-1;i++)
{
tmp = rights[tmp];
printf("%d ",tmp);
}
printf("%d\n",rights[tmp]);
return 0;
}