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 }
原文地址:https://www.cnblogs.com/joyeecheung/p/2813550.html