题意:每次找出第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. 在WIN32 DLL中使用MFC

    最近用WIN32 DLL,为了方便要用到MFC的一些库,又不想转工程,就网上找了很多方法,发现没有详细的介绍,有的也行不通,现在成功在WIN32 DLL中使用了MFC,记录一下以防以后用到忘记 一.修 ...

  2. 如何在WINDOWS下编译BOOST C++库 .

    如何在WINDOWS下编译BOOST C++库 cheungmine 2008-6-25   写出来,怕自己以后忘记了,也为初学者参考.使用VC8.0和boost1.35.0.   1)下载boost ...

  3. IntelliJ Idea12 破解码与中文乱码配置

    user name:JavaDeveloper serial number:92547-KY2BB-QZ0S1-PEZCV-HUT8Q-6RYY4        会出现Ok可以点击就会将软件 安装后, ...

  4. codeforces #309 div1 C

    首先我们会发现所有的人构成了一个图 定义相爱为 在一个集合里 定义相恨为 不在一个集合里 很容易发现满足条件的图一定是一个二分图 那么分类讨论如下: 1.如果出现不合法 答案为0 2.如果不是一个二分 ...

  5. mybatis的知识点总结

    1.接口绑定:两种方法,基于注解或者基于xml文档mapper,但要注意mapper的namespace要与接口路径完全一致. 2.orm格式转换:通过设置resultMap和ResultType,将 ...

  6. 提供几个可注册的edu邮箱链接

    旧版的邮箱大全有edu邮箱的专题页面,放出来2个国内edu.cn邮箱的注册地址:@live.shop.edu.cn和@abc.shop.edu.cn,现在已经停止开放注册了. 其实旧版中还做了个隐藏的 ...

  7. 摄像头(2)调用系统拍照activity来录像

    import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager ...

  8. JsonPath详解

    JsonPath is to JSON what XPATH is to XML, a simple way to extract parts of a given document. JsonPat ...

  9. get mac 20150202

    getmac.sh #!/bin/sh cat oui.txt|sed -e :a -e '$!N;s/\n\s/=/;ta' -e 'P;D' | sed 's/(hex)\+/=/g' | sed ...

  10. poj3275

    比较笨啊,一直在想,到底问几次绝对能知道所有的关系呢? 后来看了题解才知道,问一次最少确定一对关系………… 这就好办le,n头牛有C(2,n)个关系 现在给出m条边,以确定的关系有多少呢?直接dfs啊 ...