题目大意:给你 N 个数,M 条指令,问当执行完这些指令时,所有在奇数位置上的数的和
解题思路:用链表来模拟,值得注意的是,不能真的去执行反转操作,因为数据量过大,有可能会超时
#include <cstdio> struct Node { int left; int right; }; struct Node node[100010]; void link(int x, int y) //链接相邻的两个元素 { node[y].left = x; node[x].right = y; } void moveleft(int x, int y) // 1 x 3 y 5 --> 1 3 x y 5 { //把 x 移出序列 link(node[x].left, node[x].right); //把 x 插入到 y 的前面 link(node[y].left, x); link(x, y); } void moveright(int x, int y) // 1 x 3 y 5 --> 1 3 y x 5 { //把 x 移出序列 link(node[x].left, node[x].right); //把 x 插入到 y的后面 link(x, node[y].right); link(y, x); } void exchange(int x, int y) //对调 x 与 y 位置 { struct Node X, Y; //记录下 x, y 的位置, 避免互换位置的过程中 x, y 之前所在的位置的信息, 因 x, y 的位置的改变而改变 X.left = node[x].left; X.right = node[x].right; Y.left = node[y].left; Y.right = node[y].right; if (node[x].right == y) // x y 相邻的情况: x y --> y x { link(X.left, y); link(y, x); link(x, Y.right); } else if (node[y].right == x) // y x 相邻的情况: y x --> x y { link(Y.left, x); link(x, y); link(y, X.right); } else // x y 不相邻的情况:1 x 3 y 5 --> 1 y 3 x 5 { // 让 y 占据 x 的位置 link(X.left, y); link(y, X.right); // 让 x 占据 y 的位置 link(Y.left, x); link(x, Y.right); } } int main() { int n, m, t = 0; while (scanf("%d%d", &n, &m) != EOF) { for (int i = 0; i <= n; i++) //初始化链表 数字的范围是 1 ~ n , 但我们要做成 0 ~ n + 1 的链表 link(i, i + 1); //这是为了避免 1 的左边、n 的右边没有元素所引发的问题 int change = 0; for (int i = 0; i < m; i++) { //执行 m 条指令 int x, y, command; scanf("%d",&command); if (command == 4) //当指令为 4 时我们不能真的去执行反转链表的操作, 因为操作量太大,有可能超时 change++; //实际上我们也不需要真的执行,只需记录反转的次数,并根据反转次数, 对指令 1 和 2 做反转处理即可 else { scanf("%d%d", &x, &y); if (change % 2 != 0 && command != 3) //反转链表奇数次, 就反转指令 1 和 2, 反转链表不影响指令 3 command = 3 - command; //反转链表偶数次,不会对任何的指令的执行造成影响 if (command == 1) moveleft(x, y); if (command == 2) moveright(x, y); if (command == 3) exchange(x, y); } } int flag = 1, position = 1; long long sum = 0; //结果可能超过 int 的范围 //如果是 n 是奇数或者反转次数是偶数,则不管反转多少次,奇数位置的数还是在奇数位置 if (n % 2 == 0 && change % 2 == 1) //如果是 n 的偶数, 且反转次数是奇数次,奇数位置的数在偶数位置上 flag = 0; //求 1 ~ n 里面所有在奇数位置上的数的和 for (int i = node[0].right; position <= n; i = node[i].right) { if (position % 2 == flag) //判断是求所有奇数位置的数的和,还是求所有偶数位置的的数的和 sum += i; position++; } printf("Case %d: %lld\n", ++t, sum); } return 0; }