12657 - Boxes in a Line

来源:互联网 发布:嘟嘟通话录音软件 编辑:程序博客网 时间:2024/04/29 08:20

Boxes in a Line

You have n boxes in a line on the table numbered 1…n from left to right. Your task is to simulate 4 kinds of commands:

  • 1 X Y : move box X to the left to Y (ignore this if X is already the left of Y)
  • 2 X Y : move box X to the right to Y (ignore this if X is already the right of Y)
  • 3 X Y : swap box X and Y
  • 4 : reverse the whole line.

Commands are guaranteed to be valid, i.e. X will be not equal to Y.

For example, if n = 6, after executing 1 1 4, the line becomes 2 3 1 4 5 6. Then after executing 2 3 5, the line becomes 2 1 4 5 3 6. Then after executing 3 1 6, the line becomes 2 6 4 5 3 1. Then after executing 4, then line becomes 1 3 5 4 6 2

Input

There will be at most 10 test cases. Each test case begins with a line containing 2 integers n,m(1≤n,m≤100,000). Each of the following m lines contain a command.

Output

For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to n from left to right.

Sample Input

6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4

Sample Output

Case 1: 12
Case 2: 9
Case 3: 2500050000

你有一行盒子,从左到右依次编号为1, 2, 3,…, n。可以执行以下4种指令:

  • 1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令)。
  • 2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令)。
  • 3 X Y表示交换盒子X和Y的位置。
  • 4 表示反转整条链。

指令保证合法,即X不等于Y。例如,当n=6时在初始状态下执行114后,盒子序列为2 3 1 4 5 6。接下来执行2 3 5,盒子序列变成2 1 4 5 3 6。再执行3 1 6,得到2 6 4 5 3 1。最终执行4,得到1 3 5 4 6 2。

输入包含不超过10组数据,每组数据第一行为盒子个数n和指令条数m(1≤n,m≤100000),以下m行每行包含一条指令。每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为1~n。

样例输入:

6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4

样例输出:

Case 1: 12
Case 2: 9
Case 3: 2500050000

#include <cstdio>#include <algorithm>using namespace std;const int maxNum = 100005;// 盒子int box[maxNum];// 左链表int left[maxNum];// 右链表int right[maxNum];// 连接L,R结点void link(int L, int R) {    left[R] = L;    right[L] = R;}int main() {    // n个盒子    // m条操作    int n, m, kase = 0;    while(scanf("%d%d", &n, &m) != EOF) {        // 初始化        for(int i = 1; i <= n; i++) {            // 盒子的值            box[i] = i;            // 盒子的左链表指向上一个元素            left[i] = i - 1;            // 盒子的右链表指向下一个元素            right[i] = i + 1;        }        // 通过这个操作,使链表变成循环双链表        right[0] = 1;        left[0] = n;        // 标记链表是否反转,默认为不反转        bool isRev = false;        // 操作        int op;        while(m--) {            scanf("%d", &op);            // 反转操作            if(4 == op) {                isRev = !isRev;            } else {                int X;                int Y;                scanf("%d%d", &X, &Y);                // 使交换操作中的邻接情况,由                // XY,YX两种变成XY一种                if(3 == op && right[Y] == X) {                    swap(X, Y);                }                // 反转之后,1,2操作交换                if(3 != op && isRev) {                    op = 3 - op;                }                // X已经在Y的左边了                if(1 == op && left[Y] == X) {                    continue;                }                // X已经在Y的右边了                if(2 == op && right[Y] == X) {                    continue;                }                // X的左边                int XL = left[X];                // X的右边                int XR = right[X];                // Y的左边                int YL = left[Y];                // Y的右边                int YR = right[Y];                // 将X放在Y的左边                if(1 == op) {                    // 连接X左边结点和右边结点                    link(XL, XR);                    // 连接Y的左边结点和X结点                    link(YL, X);                    // 连接X结点和Y结点                    link(X, Y);                } else if(2 == op) {                    // 将X放在Y的右边                    // 连接X左边结点和右边结点                    link(XL, XR);                    // 连接Y结点和X结点                    link(Y, X);                    // 连接X结点和Y的右边结点                    link(X, YR);                } else if(3 == op) {                    // 交换X和Y结点                    // XY相邻                    if(right[X] == Y) {                        // 连接X左边结点和Y结点                        link(XL, Y);                        // 连接Y结点和X结点                        link(Y, X);                        // 连接X结点和Y右边结点                        link(X, YR);                    } else {                        // 连接X左边结点和Y结点                        link(XL, Y);                        // 连接Y结点和X右边结点                        link(Y, XR);                        // 连接Y左边结点和X结点                        link(YL, X);                        // 连接X结点和Y右边结点                        link(X, YR);                    }                }            }        }        int node = 0;        long long ans = 0;        for(int i = 1; i <= n; i++) {            // 获取右结点            node = right[node];            // 因为结点和值一样,所以直接相加            if(i % 2 == 1) {                ans += node;            }        }        // n为偶数且链表反转        // PS:如果n为奇数,反转与不反转是一样的        if(!(n % 2) && isRev) {            // 因为是从1-n,所以反转取差就行了            ans = (long long)n * (n + 1) / 2 - ans;        }        printf("Case %d: %lld\n", ++kase, ans);    }    return 0;}
0 0
原创粉丝点击