移动盒子uva12657

题目描述

题目位置:uva12657 

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

 上面简单的中文翻译

表上一行有n个框,编号为1。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,则在执行1 1 4之后,该行变为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个测试用例。每个测试用例以一行开始,该行包含2个整数n,m(1≤n,m≤100000)。以下m行中的每一行都包含一个命令。输出对于每个测试用例,在奇数索引位置打印数字的总和。位置从左到右编号为1到n。

题目分析

有一篇文章就是说的比较透彻了

具体的一个讲解

其实就是说,这里用数组模拟了一个循环双向链表,是不一定用指针操作的

大致说两点

 具体代码实现

demo2.cpp

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 100000 + 5;
int n, left[maxn], right[maxn];

inline void link(int L, int R) {
  right[L] = R; left[R] = L;
}

int main() {
  int m, kase = 0;
  while(scanf("%d%d", &n, &m) == 2) {
    for(int i = 1; i <= n; i++) {
      left[i] = i-1;
      right[i] = (i+1) % (n+1);
    }
    right[0] = 1; left[0] = n;
    int op, X, Y, inv = 0;

    while(m--) {
      scanf("%d", &op);
      if(op == 4) inv = !inv;
      else {
        scanf("%d%d", &X, &Y);
        if(op == 3 && right[Y] == X) swap(X, Y);
        if(op != 3 && inv) op = 3 - op;
        if(op == 1 && X == left[Y]) continue;
        if(op == 2 && X == right[Y]) continue;

        int LX = left[X], RX = right[X], LY = left[Y], RY = right[Y];
        if(op == 1) {
          link(LX, RX); link(LY, X); link(X, Y);
        }
        else if(op == 2) {
          link(LX, RX); link(Y, X); link(X, RY);
        }
        else if(op == 3) {
          if(right[X] == Y) { link(LX, Y); link(Y, X); link(X, RY); }
          else { link(LX, Y); link(Y, RX); link(LY, X); link(X, RY); }
        }
      }
    }

    int b = 0;
    long long ans = 0;
    for(int i = 1; i <= n; i++) {
      b = right[b];
      if(i % 2 == 1) ans += b;
    }
    if(inv && n % 2 == 0) ans = (long long)n*(n+1)/2 - ans;
    printf("Case %d: %lld\n", ++kase, ans);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/Pxx520Tangtian/article/details/129869497
今日推荐