题目链接

题意:

有三根编号为\((1, \, 2, \, 3)\)的柱子,然后第一根柱子上有编号为\(1 \sim n(n \leq 10000)\)的盘子,从上到下第\(i\)个盘子的编号是\(A_i\),其他两根柱子是空的。

你可以进行一种操作x y,表示将第\(x\)根柱子最上面的盘子放到第\(y\)根柱子的最上面去。

输出不超过\(10^6\)次操作,使得最终所有的盘子都在同一根柱子(柱子的编号不限)上而且从上到下编号是递增的。

分析:

首先很容易想到一个\(O(n^2)\)的做法:

就是每次遇到不是\(n\)的盘子的时候就扔到柱子\(3\)上去,否则就扔到柱子\(2\)上去。

然后重复这一过程,在\(n-1\)号盘子所在的柱子上,遇到不是\(n-1\)的就扔到其他柱子上,遇到\(n-1\)就扔到柱子\(2\),也就是\(n\)号盘子的上面。

然后有一个\(O(n^{\frac{3}{2}})\)的做法。是基于平方分割的思想,每次取出\(\sqrt{n}\)个编号最大的盘子,然后暴力用\(O((\sqrt{n})^2)=O(n)\)次操作将其排序。

最后是\(O(nlogn)\)的做法:

这种做法是基于分治的思想,和快排的思路一模一样:先分解问题然后再合并问题。

我们规定从上到下递增的是顺序,从上到下递减的是逆序

分:

对于某个柱子上乱序的区间\([l, \, r]\),如果我们要将它顺序排序,我们可以将\([l, \, mid]\)中的盘子和\([mid+1, \, r]\)中的盘子分别扔到其他两根柱子上。

然后对这两个根柱子上的盘子逆序排序。

合:

左右区间逆序排好序后然后按照从大到小的顺序再放回原来的柱子上,使得整个\([l, \, r]\)是顺序的。

对\([l, \, mid]\)和\([mid+1, \, r]\)这两个区间逆序排序,这样问题的规模就减小了一半。

相反地,如果要对一个区间逆序排序,就要先对它的左右区间顺序排序,然后合并。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; const int maxn = 10000 + 10;
int n;
int cnt[3], t[3][maxn];
int lft[] = { 1, 0, 0 };
int rgh[] = { 2, 2, 1 }; void op(int i, int j) {
printf("%d %d\n", i + 1, j + 1);
t[j][cnt[j]] = t[i][cnt[i]-1];
cnt[j]++; cnt[i]--;
} void solve(int cur, int l, int r, bool inv) {
if(l == r) return;
int mid = (l + r) / 2;
for(int i = 1; i <= r-l+1; i++) {
if(t[cur][cnt[cur]-1] <= mid) op(cur, lft[cur]);
else op(cur, rgh[cur]);
}
solve(lft[cur], l, mid, !inv);
solve(rgh[cur], mid+1, r, !inv);
if(!inv) {
for(int i = mid + 1; i <= r; i++) op(rgh[cur], cur);
for(int i = l; i <= mid; i++) op(lft[cur], cur);
} else {
for(int i = l; i <= mid; i++) op(lft[cur], cur);
for(int i = mid + 1; i <= r; i++) op(rgh[cur], cur);
}
} int ans; void dfs(int t) {
if(t == 1) return;
ans += t * 2;
dfs(t / 2);
dfs(t - t / 2);
} int main()
{
scanf("%d", &n);
cnt[0] = n;
for(int i = n-1; i >= 0; i--) scanf("%d", &t[0][i]); ans = 0;
dfs(n);
printf("%d\n", ans);
solve(0, 1, n, false); return 0;
}

最新文章

  1. 关于tarjan算法的理解
  2. [POJ3111]K Best(分数规划, 二分)
  3. 从svn检出项目---------不是web项目
  4. [BZOJ2788][Poi2012]Festival
  5. WCF:2个常见错误
  6. warning:performSelector may cause a leak because its selector
  7. HTML元素的ID和Name属性的区别
  8. React-Native 之 项目实战(五)
  9. 关于Iscroll.js 的滑动和Angular.js路由冲突问题
  10. robotframework的学习笔记(十五)----robotframework标准库Collections
  11. 稍微记录下Django2.2使用MariaDB和MySQL遇到的坑
  12. JS执行环境,作用域链及非块状作用域
  13. mysql----------原生的sql里面如何根据case then排序
  14. 【js高程学习笔记】Object类型
  15. CobaltStrike3.12/13 破解
  16. coalesce :返回参数(列名)中第一个非NULL值的字段值
  17. what&#39;s the 场外交易
  18. 【Alpha】第八次Scrum meeting
  19. Java编程的逻辑 (67) - 线程的基本协作机制 (上)
  20. GridView动态添加列并判断绑定数据DataTable的列类型控制展示内容

热门文章

  1. 求逆欧拉函数(arc)
  2. DatabaseMetaData类
  3. vue2.0:(七)、vue-resource
  4. npm使用快速的安装源(nrm)
  5. ORACLE中能否找到未提交事务的SQL语句
  6. mongodb安全整理
  7. POJ Charlie&#39;s Change 查理之转换(多重背包,变形)
  8. Spark性能调优之道——解决Spark数据倾斜(Data Skew)的N种姿势
  9. 撤销git pull命令
  10. 两个有序数列,求中间值 Median of Two Sorted Arrays