12657 - Boxes in a Line
2016-05-09 20:09
316 查看
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; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 1.10055 - Hashmat the brave warrior
- 2.10071 - Back to High School Physics
- 3.458 - The Decoder
- 4.694 - The Collatz Sequence
- 6.494 - Kindergarten Counting Game
- 7.490 - Rotating Sentences
- 8.414 - Machined Surfaces
- 9.488 - Triangle Wave
- A.457 - Linear Cellular Automata
- B.489 - Hangman Judge