sicily 1934. 移动小球
Description
你有一些小球,从左到右依次编号为1,2,3,...,n. 你可以执行两种指令(1或者2)。其中, 1 X Y表示把小球X移动到小球Y的左边, 2 X Y表示把小球X移动到小球Y右边。 指令保证合法,即X不等于Y。 例如,初始状态1,2,3,4,5,6的小球执行1 1 4后,小球1被移动到小球4的左边,即2,3,1,4,5,6。如果再执行2 3 5,结点3将会移到5的右边,即2,1,4,5,3,6。
Input
第一行为一个整数t(0<t<10),表示测试用例个数。每个测试用例的第一行为两个整数n(1<n<=500000)和m(0<m<100000),n表示小球的个数,m为指令条数,以下m行每行为一条指令。
Output
为每个测试用例单独输出一行,从左到右输出最后序列,每个数字后面跟一个空格。
和LRJ的白书上用来讲链表的例题几乎是一模一样的-___-!! 只不过书上那题用来表示移动方向的不是1和2,是A和B
如果用小球的绝对位置来做,每动一个小球其他小球的位置信息都要改,应该(肯定)会超时,如果只用相对位置做的话,每次只要改几个相关小球的位置信息就好了,效率高很多。left[i]是编号为i的小球左边的球的编号,其他类推。为了方便处理(避免越界和便于打印),left和right两个数组模拟出来的一堆小球里最左边有一个虚拟的小球,编号是0,最右边有一个虚拟的小球n+1。当然它们不会出现在输出中……
算是做的第一道链表题了,虽然不是用结构体+指针而是数组+下标做的
AC runtime 0.26sec,不知道为啥有一次变成0.28sec了,当时sicily在抽风……
View Code
1 #include<stdio.h> 2 #define MAXN 500100 3 int left[MAXN] = {0}; 4 int right[MAXN] = {0}; 5 6 void link( int x, int y ); 7 8 int main() 9 { 10 int t; 11 int n, m; 12 int x, y; 13 int side; 14 int i; 15 int ball; 16 17 scanf("%d", &t); 18 19 while( t-- ) 20 { 21 scanf( "%d %d", &n, &m ); 22 23 for ( i = 0; i <= n; i++ ) 24 { 25 link( i, i + 1 ); 26 } 27 28 while ( m-- ) 29 { 30 scanf("%d %d %d", &side, &x, &y ); 31 32 link( left[x], right[x] ); 33 34 if( side == 1 ) 35 { 36 link( left[y], x ); 37 link( x, y ); 38 } 39 40 else 41 { 42 link( x, right[y] ); 43 link( y, x ); 44 } 45 } 46 47 for ( ball = right[0]; ball != n + 1; ball = right[ball] ) 48 { 49 printf("%d ", ball); 50 } 51 52 printf("\n"); 53 } 54 return 0; 55 56 } 57 58 void link( int x, int y ) 59 { 60 right[x] = y; 61 left[y] = x; 62 }