Crane UVA - 1611

题目传送门

题意:给你n个数字的序列,你可以一次操作一个区间(区间大小是偶数),交换区间的前半部分与后半部分,用不超过9^6的操作数使这个序列变成一个升序列。

思路:这个我一开始理解的是要用最少的操作数,然后就想了好久都没有想出来,但是发现了只需要从左到右进行操作就可以,每一数字最多只需要两次操作就可以了,但是一只输出的操作不是操作次数最少的(十分崩溃啊),然后后来发现不需要次数最少。。。。。。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MAXN 100010
#define MAXE 210
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define PI acos(-1.0)

using namespace std;

int arr[MAXN];

struct Node {
  int left;
  int right;
};

void SWAP(int left, int right) {
  for (int i = left, j = left + (right - left + 1) / 2; j <= right; ++j, ++i)
    swap(arr[i], arr[j]);
}

int main() {
  std::ios::sync_with_stdio(false);
  int T;
  cin >> T;
  for (int kase = 1; kase <= T; ++kase) {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
      cin >> arr[i];
    }
    vector vec;
    Node t;
    for (int i = 1; i <= n; ++i) {
      if (arr[i] == i)
        continue;
      int pos = 0;
      for (int j = i + 1; j <= n; ++j) {
        if (arr[j] == i) {
          pos = j;
          break;
        }
      }
      if (2 * pos - i - 1 > n) {
        if ((pos - i) % 2) {
          t.left = i;
          t.right = pos;
          vec.push_back(t);
          SWAP(i, pos);
        } else {
          t.left = i + 1;
          t.right = pos;
          vec.push_back(t);
          SWAP(i + 1, pos);
        }
        i--;
      } else {
        t.left = i;
        t.right = 2 * pos - i - 1;
        vec.push_back(t);
        SWAP(i, 2 * pos - i - 1);
      }
    }
    cout << vec.size() << endl;
    for (int i = 0; i < vec.size(); ++i) {
      cout << vec[i].left << " " << vec[i].right << endl;
    }
  }
  return 0;
}

/*
2
6
5 4 6 3 2 1
5
1 2 3 4 5
*/

你可能感兴趣的:(UVA,贪心)