打卡信奥刷题(1599)用C++实现信奥 P7128 「RdOI R1」序列(sequence)

P7128 「RdOI R1」序列(sequence)

题目描述

有一序列 xxx ,长度为 qqq ,序列中的每个数只出现一次。

即:序列 xxx111qqq 的一个排列。

对于序列 xxx 的操作只有一种:对于一个数 xix_ixi ,你可以使其与 x2ix_{2i}x2ix2i+1x_{2i+1}x2i+1 交换位置(如果它们存在的话)。

现在请你使序列 xxx 变为一个升序序列,并按顺序输出你进行的操作。

输入格式

输入数据共 222 行。

111 行, 111 个正整数,qqq

222 行, qqq 个正整数, x1~qx_{1~q}x1q

输出格式

输出数据共 ansansans 行, ansansans 表示你的操作次数。

111 ~ ansansans 行,每行两个整数,iiijjj ,表示交换 xix_ixixjx_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说明:

交换 222333 ,序列变为:2,1,32,1,32,1,3

再交换 222111 ,序列变为:1,2,31,2,31,2,3

【数据范围】

对于 40%40\%40% 的数据,3≤q≤2103 \le q \le 2^{10}3q210

对于 100%100\%100% 的数据,3≤q≤2173 \le q \le 2^{17}3q2171≤xi≤q1 \le x_i \le q1xiq

【提示】

  • 使用 Special Judge。
  • q=2p−1(p∈N∗)q = 2 ^ p - 1(p \in \mathbb{N}^*)q=2p1(pN)
  • 最多进行 2q×⌈log⁡2q⌉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考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值