P7128 「RdOI R1」序列(sequence)
题目描述
有一序列 xxx ,长度为 qqq ,序列中的每个数只出现一次。
即:序列 xxx 是 111 到 qqq 的一个排列。
对于序列 xxx 的操作只有一种:对于一个数 xix_ixi ,你可以使其与 x2ix_{2i}x2i 或 x2i+1x_{2i+1}x2i+1 交换位置(如果它们存在的话)。
现在请你使序列 xxx 变为一个升序序列,并按顺序输出你进行的操作。
输入格式
输入数据共 222 行。
第 111 行, 111 个正整数,qqq。
第 222 行, qqq 个正整数, x1~qx_{1~q}x1~q。
输出格式
输出数据共 ansansans 行, ansansans 表示你的操作次数。
第 111 ~ ansansans 行,每行两个整数,iii ,jjj ,表示交换 xix_ixi 和 xjx_jxj 的位置 (i<j)(i < j)(i<j)。
输入输出样例 #1
输入 #1
3
3 1 2
输出 #1
1 3
1 2
输入输出样例 #2
输入 #2
7
1 3 2 7 6 4 5
输出 #2
2 4
1 2
1 3
3 7
2 5
1 2
1 3
3 6
1 2
2 5
1 3
1 2
2 4
1 2
1 3
1 2
说明/提示
【样例说明】
样例#1说明:
交换 222 和 333 ,序列变为:2,1,32,1,32,1,3。
再交换 222 和 111 ,序列变为:1,2,31,2,31,2,3。
【数据范围】
对于 40%40\%40% 的数据,3≤q≤2103 \le q \le 2^{10}3≤q≤210。
对于 100%100\%100% 的数据,3≤q≤2173 \le q \le 2^{17}3≤q≤217,1≤xi≤q1 \le x_i \le q1≤xi≤q。
【提示】
- 使用 Special Judge。
- q=2p−1(p∈N∗)q = 2 ^ p - 1(p \in \mathbb{N}^*)q=2p−1(p∈N∗)
- 最多进行 2q×⌈log2q⌉2q\times\lceil\log_2 q\rceil2q×⌈log2q⌉ 次操作。
- 样例的输出数据只是众多方案中的一种。
- 因为是
special judge
,因此不提供附加样例。
【文件读入读出】(模拟,提交代码时不需使用)
- 文件名:
sequence.cpp
- 读入文件名:
sequence.in
- 读出文件名:
sequence.out
C++实现
#include<cctype>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 131072;
int q, x[N], p[N], t[N];
int read() {
int x = 0, f = 1; char c;
while (!isdigit(c = getchar())) f -= (c == '-') * 2;
while (isdigit(c)) x = x * 10 + f * (c - 48), c = getchar();
return x;
}
int main() {
q = read();
for (int i = 1; i <= q; ++i) p[x[i] = read()] = i;
for (int i = q; i > 1; --i) {
if (p[i] == i) continue;
while (p[i] > 1) {
printf("%d %d\n", p[i] / 2, p[i]);
swap(x[p[i]], x[p[i] / 2]);
swap(p[i], p[x[p[i]]]);
}
int j = 0;
for (int k = i; k > 1; k /= 2) t[++j] = k; t[++j] = 1;
for (int k = j; k > 1; --k) {
printf("%d %d\n", t[k], t[k - 1]);
swap(x[t[k]], x[t[k - 1]]);
swap(p[x[t[k]]], p[x[t[k - 1]]]);
}
}
return 0;
}
后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容