思路:
原版代码:
1 #include<cstdio>
2 #include<algorithm>
3 using namespace std;
4
5 const int maxn = 100000 + 5;
6 int n, left[maxn], right[maxn];
7 /*left;编号为i的盒子左边的编号
8 right:右边的编号
9 inv表示有没有执行过操作4(如果inv=1,再执行一次操作4,则inv变为0)
10 */
11 inline void link(int L, int R) //L和R连接
12 {
13 right[L] = R; left[R] = L;
14 }
15
16 int main()
17 {
18 int m, kase = 0;
19 while(scanf("%d%d", &n, &m) == 2)
20 {
21 for(int i = 1; i <= n; i++)
22 {
23 left[i] = i-1;
24 right[i] = (i+1) % (n+1);//第n个右边是第1个
25 }
26 right[0] = 1; left[0] = n;
27 int op, X, Y, inv = 0;
28
29 while(m--)
30 {
31 scanf("%d", &op);
32 if(op == 4) inv = !inv;
33 else
34 {
35 scanf("%d%d", &X, &Y);
36 if(op == 3 && right[Y] == X) swap(X, Y);//X在Y右边,交换后X在Y左边 YX->XY
37 if(op != 3 && inv) op = 3 - op;// 1,2要受inv的影响,AB inv后变成BA,相当于把1,2反过来
38 if(op == 1 && X == left[Y]) continue;//X已经在Y左边
39 if(op == 2 && X == right[Y]) continue;//X已经在Y右边
40
41 int LX = left[X], RX = right[X], LY = left[Y], RY = right[Y];
42 if(op == 1) //X到Y左
43 {
44 link(LX, RX); //X从链表中取出,连接X左右节点
45 link(LY, X);//X与Y左边的节点相连
46 link(X, Y);//X连接到Y左边
47 }
48 else if(op == 2) //X到Y右
49 {
50 link(LX, RX); link(Y, X); link(X, RY);
51 }
52 else if(op == 3) //X Y交换
53 {
54 if(right[X] == Y) //Y在X右边 LX->X->Y->RY
55 {
56 link(LX, Y); //LX->Y
57 link(Y, X);//LX->Y->X
58 link(X, RY); //LX->Y->X->RY
59 }
60 else
61 {
62 link(LX, Y);
63 link(Y, RX);
64 link(LY, X);
65 link(X, RY);
66 }
67 }
68 }
69 }
70
71 int b = 0;
72 long long ans = 0;
73 for(int i = 1; i <= n; i++)
74 {
75 b = right[b];
76 if(i % 2 == 1) ans += b;//奇数位置加上其盒子编号
77 }
78 if(inv && n % 2 == 0)
79 ans = (long long)n*(n+1)/2 - ans;
80 printf("Case %d: %lld\n", ++kase, ans);
81 }
82 return 0;
83 }