题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成。输出每次操作的$P_i$,要求稳定排序(在括号外的是多组数据,括号内的是单组数据,四倍经验)

题解:可以用平衡数维护序列,只要维护求一个数的位置和区间翻转即可

卡点:查询位置时未$pushdown$

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 100010
int n;
int s[maxn], rnk[maxn], mp[maxn];
inline bool cmp(int a, int b) {
if (s[a] == s[b]) return a < b;
return s[a] < s[b];
}
namespace Treap {
int rc[maxn], lc[maxn], pri[maxn], V[maxn], sz[maxn];
int fa[maxn], tg[maxn];
int root, idx, ta, tb, tmp, res;
int seed = 20040826;
inline int rand() {return seed *= 48271;}
inline int nw(int x) {
V[++idx] = x;
sz[idx] = 1;
pri[idx] = rand();
lc[idx] = rc[idx] = fa[idx] = tg[idx] = 0;
return idx;
}
inline int update(int rt) {
sz[rt] = sz[lc[rt]] + sz[rc[rt]] + 1;
fa[lc[rt]] = fa[rc[rt]] = rt;
return rt;
}
inline void pushdown(int rt) {
if (tg[rt]) {
tg[rt] = 0;
std::swap(lc[rt], rc[rt]);
tg[lc[rt]] ^= 1, tg[rc[rt]] ^= 1;
}
}
void split(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
pushdown(rt);
if (sz[lc[rt]] < k) split(rc[rt], k - sz[lc[rt]] - 1, rc[rt], y), x = update(rt);
else split(lc[rt], k, x, lc[rt]), y = update(rt);
}
}
int merge(int x, int y) {
if (!x || !y) return x | y;
pushdown(x), pushdown(y);
if (pri[x] < pri[y]) {rc[x] = merge(rc[x], y); return update(x);}
else {lc[y] = merge(x, lc[y]); return update(y);}
} void debug(int rt) {
if (lc[rt]) debug(lc[rt]);
printf("%d\n", V[rt]);
if (rc[rt]) debug(rc[rt]);
} inline void insert(int x) {
if (!root) root = nw(x);
else root = merge(root, nw(x));
}
int S[maxn], top;
inline int gtrnk(int x) {
top = 0;
for (int i = x; i; i = fa[i]) S[++top] = i;
for (; top; top--) pushdown(S[top]);
res = sz[lc[x]] + 1;
while (fa[x]) {
if (rc[fa[x]] == x) res += sz[lc[fa[x]]] + 1;
x = fa[x];
}
return res;
}
inline void reverse(int l, int r) {
if (l > r) std::swap(l, r);
split(root, r, tmp, tb);
split(tmp, l - 1, ta, tmp);
tg[tmp] ^= 1;
root = merge(ta, merge(tmp, tb));
}
inline void clear() {
idx = root = 0;
}
}
int main() {
scanf("%d", &n);
while (true) {
if (!n) break;
for (int i = 1; i <= n; i++) {
scanf("%d", s + i);
rnk[i] = i;
}
std::sort(rnk + 1, rnk + n + 1, cmp);
for (int i = 1; i <= n; i++) mp[rnk[i]] = i;
for (int i = 1; i <= n; i++) Treap::insert(s[i]);
for (int I = 1, i = rnk[I]; I <= n; i = rnk[++I]) {
int res = Treap::gtrnk(i);
printf("%d", res);
putchar(I == n ? '\n' : ' ');
Treap::reverse(I, res);
}
scanf("%d", &n);
if (n) {
Treap::clear();
}
}
return 0;
}

  

[UVA1402]Robotic Sort;[SP2059]CERC07S - Robotic Sort([洛谷P3165][CQOI2014]排序机械臂;[洛谷P4402][Cerc2007]robotic sort 机械排序)的更多相关文章

  1. 洛谷P3165 [CQOI2014]排序机械臂

    题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品 ...

  2. 洛谷P3165 [CQOI2014]排序机械臂 Splay维护区间最小值

    可以将高度定义为小数,这样就完美的解决了优先级的问题. Code: #include<cstdio> #include<algorithm> #include<cstri ...

  3. 洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序

    FHQ_Treap 太神辣 蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目 因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每 ...

  4. [BZOJ1552][Cerc2007]robotic sort

    [BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...

  5. 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 806  Solved: 329[Submit][ ...

  6. 【BZOJ】【1552】【Cerc2007】robotic sort / 【3506】【CQOI2014】排序机械臂

    Splay 离散化+Splay维护序列…… 好吧主要说一下我做这道题遇到的几个错误点: 1.离散化 2.由于找到的这个数的位置一定是大于等于 i 的,所以其实在把它splay到根以后,i 结点只能sp ...

  7. BZOJ 1552: [Cerc2007]robotic sort( splay )

    kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...

  8. 【BZOJ1552】[Cerc2007]robotic sort Splay

    [BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...

  9. bzoj 1552: [Cerc2007]robotic sort

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1198  Solved: 457[Submit] ...

随机推荐

  1. 【BGP的基本配置】

    BGP的基本配置 一:根据项目需求搭建好拓扑图如下 二:配置 1:首先进行理论分析:RT1和RT2,3分别属于不同的AS;在RT1和RT2之间建立EBGP关系,在确保RT3可以学到RT1的8.1.1. ...

  2. sklearn fit transform fit_transform

    scikit-learn提供了一系列转换库,他们可以清洗,降维,提取特征等. 在数据转换中有三个很重要的方法,fit,fit_transform,transform ss=StandardScaler ...

  3. JDK5后的特性整理

    为了大家对JDK有一个全面的了解,下面是我从网上查找并整理了JDK5以后的所有关键新特性!(将会持续更新中) JDK5新特性 自动装箱与拆箱 枚举 静态导入 可变参数(Varargs) 内省(intr ...

  4. phpstudy apache启动失败,80端口占用问题解决方案

    安装phpstydy,启动apache时,启动失败,提示80端口占用,需要将占用80端口的服务进程关闭 1.运行cmd, netstat -ano 找到80端口对应的pid  4 2.一般都是调用 h ...

  5. js中的逻辑与和逻辑或随笔

    逻辑与:&&,都真才真 逻辑或:||,一真都真 逻辑运算两侧不都是布尔值时,会隐式转换为布尔值转换规则:转换为true:非0数字(包含infinity).非空字符串转换为false:0 ...

  6. print(__file__)返回<encoding error>的问题

    今天写了一下代码,本来是想得到当前文件的上面三层的目录的,结果返回的却是错误 import os import sys print(__file__) # 得到上上层目录的路径之后,加入到默认的环境变 ...

  7. 数据结构的C语言基础

    数据结构的C语言基础 1. 数据输出 printf()函数为格式输出函数,它存在于标准函数库中,在C语言程序中可以直接调用,但程序源文件的开头必须包含以下命令: #include < stdi ...

  8. 初识python 函数(定义,传参,返回值)

    python基础(二): 菜鸟教程基础知识讲解的非常全面,内容选择我认为的重点输出一遍 函数: 定义一个函数: 你可以定义一个由自己想要功能的函数,以下是简单的规则: def fun(arg): pa ...

  9. centos 安装java1.8

    https://www.cnblogs.com/xuliangxing/p/7066913.html

  10. Educational Codeforces Round 47 (Rated for Div. 2) :B. Minimum Ternary String

    题目链接:http://codeforces.com/contest/1009/problem/B 解题心得: 题意就是给你一个只包含012三个字符的字符串,位置并且逻辑相邻的字符可以相互交换位置,就 ...