题意:每次找出第i大的数的位置p输出,然后将i~p之间的数反转。

题解:每次把要的区间转成一棵子树,然后更新。因为每次将第i小的数转到了了i,所以k次操作后,可知前k个数一定是最小的那k个数,所以以后的操作一定不会和前k个数有关,所以每次操作后可以把操作完的数删掉。所以每次把p转到根,然后翻转左子树,删除根就可以了。(也就是p不需要翻转

这个splay处理比较特殊,每个结点的序号就是一开始的位置。splaytree中第i个结点的序号就是第i个数一开始的位置,然后对于每个数排序,记录一开始的位置,就可以在树中直接找到要操作的结点了。

总之。。很神奇。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF = 0x5f5f5f5f;
const int N = ; int root, tot;
int sz[N], pre[N], ch[N][], rev[N]; bool which_son(int o) { //判断一个结点是不是父结点的右儿子
return ch[pre[o]][] == o;
} void update_rev(int o) {
if (!o) return ;
swap(ch[o][], ch[o][]);
rev[o] ^= ;
} void push_up(int o) {
sz[o] = sz[ch[o][]] + sz[ch[o][]] + ;
} void push_down(int o) {
if (rev[o]) {
update_rev(ch[o][]);
update_rev(ch[o][]);
rev[o] = ;
}
} void build(int &o, int l, int r, int fa) {
if (l > r) return ;
int m = (l+r) >> ;
o = m;
pre[o]= fa;
ch[o][] = ch[o][] = ;
sz[o] = ;
rev[o] = ;
build(ch[o][], l, m-, o);
build(ch[o][], m+, r, o);
push_up(o);
} void init(int n) {
root = tot = ;
pre[] = sz[] = ch[][] = ch[][] = rev[] = ;
build(root, , n, );
push_up(root);
} void rotate(int o, int d) {
int fa = pre[o];
push_down(fa);
push_down(o);
ch[fa][!d] = ch[o][d];
pre[ch[o][d]] = fa;
pre[o] = pre[fa];
if (pre[fa]) ch[pre[fa]][which_son(fa)] = o;
pre[o] = pre[fa];
ch[o][d] = fa;
pre[fa] = o;
push_up(fa);
} void splay(int o, int goal) {
push_down(o);
while (pre[o] != goal) {
if (pre[pre[o]] == goal) {
push_down(pre[o]);
push_down(o);
rotate(o, !which_son(o));
} else {
push_down(pre[pre[o]]);
push_down(pre[o]);
push_down(o);
int fa = pre[o];
int d = !which_son(fa);
if (ch[fa][d] == o) {
rotate(o, !d);
rotate(o, d);
} else {
rotate(fa, d);
rotate(o, d);
}
}
}
push_up(o);
if (goal == ) root = o;
} int get_max(int o) {
push_down(o);
while (ch[o][]) {
o = ch[o][];
push_down(o);
}
return o;
} void remove() {
if (ch[root][] == ) {
root = ch[root][];
pre[root] = ;
} else {
int m = get_max(ch[root][]);
splay(m, root);
ch[m][] = ch[root][];
pre[ch[root][]] = m;
root = m;
pre[root] = ;
push_up(root);
}
} struct node {
int v, id;
bool operator<(const node rhs) const {
if (v == rhs.v) return id < rhs.id;
return v < rhs.v;
}
} a[N]; int main()
{
//freopen("in.txt", "r", stdin);
int n;
while (~scanf("%d", &n) && n) {
for (int i = ; i <= n; ++i) {
scanf("%d", &a[i].v);
a[i].id = i;
}
sort(a+, a++n);
init(n);
for (int i = ; i < n; ++i) {
splay(a[i].id, );
printf("%d ", sz[ch[a[i].id][]]+i);
update_rev(ch[a[i].id][]);
remove();
}
printf("%d\n", n);
} return ;
}

HDU 1890--Robotic Sort(Splay Tree)的更多相关文章

  1. HDU 1890 Robotic Sort (splay tree)

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  2. HDU 1890 Robotic Sort(splay)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1890 [题意] 给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i ...

  3. hdu 1890 Robotic SortI(splay区间旋转操作)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 题解:splay又一高级的功能,区间旋转这个是用线段树这些实现不了的,这题可以学习splay的旋 ...

  4. hdu 1890 Robotic Sort(splay 区间反转+删点)

    题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的sp ...

  5. 伸展树(Splay Tree)进阶 - 从原理到实现

    目录 1 简介 2 基础操作 2.1 旋转 2.2 伸展操作 3 常规操作 3.1 插入操作 3.2 删除操作 3.3 查找操作 3.4 查找某数的排名.查找某排名的数 3.4.1 查找某数的排名 3 ...

  6. 数据结构(二) --- 伸展树(Splay Tree)

    文章图片和代码来自邓俊辉老师课件 概述 伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由丹尼尔·斯立特Daniel Sleator ...

  7. HDU 1890 Robotic Sort | Splay

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Pr ...

  8. 数据结构(Splay平衡树):HDU 1890 Robotic Sort

    Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  9. 纸上谈兵:伸展树(splay tree)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每次 ...

随机推荐

  1. Making your local server accessible from anywhere

    In reality you probably don’t want to host you websites on your local computer unless you have a ver ...

  2. http://jingyan.baidu.com/article/a378c960630e61b329283045.html

    http://jingyan.baidu.com/article/a378c960630e61b329283045.html

  3. Oracle导入(imp )与导出(exp )

    导出exp username/password@orcl file=db.dmp 导入imp username/password@orcl file=h:\db.dmp  full=y 备注:在导入之 ...

  4. UINavigationController使用详解

    UINavigationController使用详解 有一阵子没有写随笔,感觉有点儿手生.一个多月以后终于又一次坐下来静下心写随笔,记录自己的学习笔记,也希望能够帮到大家. 废话少说回到正题,UINa ...

  5. log4jdbc-remix安装配置

    1.maven安装依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w ...

  6. thinkphp 分组

    分组 配置项: // 开启分组 'APP_GROUP_LIST'=>'Home,Admin', // 默认分组 'DEFAULT_GROUP'=>'Home', 涉及分组: 配置文件分组, ...

  7. ANDROID_MARS学习笔记_S01_012_SeekBar

    1.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns: ...

  8. 220. Contains Duplicate III

    题目: Given an array of integers, find out whether there are two distinct indices i and j in the array ...

  9. Sqlmap基础(二)

    sqlmap.py -r req1.txt --dbms Oracle --risk

  10. Java API ——包装类

    1.包装类的概述 · 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据. · 常用的操作之一:用于基本数据类型与字符串之间的转换. · 基本类型和包装类的对应 为了对基本数据 ...