http://acm.hdu.edu.cn/showproblem.php?pid=1890

题意:有一个无序序列,经过不断地翻转,使得最后的序列是一个升序的序列,而且如果相同数字要使在原本序列靠前的在前面。对于每一个位置,输出于哪个位置翻转。

思路:想通了之后其实挺简单的,不过挺巧妙。一开始先记录每一个位的pos,并对数组升序排序,然后我们从小到大枚举数组里的元素,对于每个元素,我们可以知道:i 就是翻转后应当在序列中的位置,a[i].pos就是它在原序列的位置。这个时候,我们只要在建树的时候利用中序遍历就是原数组的样子的性质,让节点的值就是它在原数组的位置,即建一个新的节点的时候,x 就是在原数组中的编号,例如样例:3 4 5 1 6 2,那么对应的节点的值就是 1 2 3 4 5 6 了。然后对于每一个询问,我们知道了它在原序列的位置,我们将它的位置(即节点本身的值)旋转到根节点,那么它的左子树的 sz 就是它目前所在的位置(因为一开始多了一个节点),然后再对 目标位置 和 所在的位置进行区间翻转,就可以完成了。

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define INF 0x7fffffff
#define lson ch[x][0]
#define rson ch[x][1]
#define keytree ch[ch[root][1]][0]
#define rootkey ch[root][1]
#define N 300000
struct node
{
int val, id;
}a[N];
struct SplayTree {
int num[N], sz[N], fa[N], ch[N][], root, rev[N];
int n; void PushUp(int x) {
sz[x] = sz[lson] + sz[rson] + ;
} void PushDown(int x) {
if(rev[x]) {
swap(lson, rson);
if(lson) rev[lson] ^= ;
if(rson) rev[rson] ^= ;
rev[x] = ;
}
} int NewNode(int f, int k, int kind) {
int x = k;
fa[x] = f;
rev[x] = ch[x][] = ch[x][] = ;
sz[x] = ; ch[f][kind] = x;
return x;
} void Build(int l, int r, int &x, int f, int kind) {
if(l > r) return ;
int m = (l + r) >> ;
x = NewNode(f, m, kind);
Build(l, m - , ch[x][], x, );
Build(m + , r, ch[x][], x, );
PushUp(x);
} void Init() {
root = ;
ch[][] = ch[][] = fa[] = rev[] = sz[] = ;
root = NewNode(, n + , );
rootkey = NewNode(root, n + , );
sz[root] = ;
Build(, n, keytree, rootkey, );
PushUp(rootkey); PushUp(root);
} void Rotate(int x, int kind) {
int y = fa[x], z = fa[y];
PushDown(y); PushDown(x);
ch[y][!kind] = ch[x][kind];
if(ch[x][kind]) fa[ch[x][kind]] = y;
if(z) {
if(y == ch[z][]) ch[z][] = x;
else ch[z][] = x;
}
fa[x] = z; fa[y] = x;
ch[x][kind] = y;
PushUp(y);
} void Splay(int x, int goal) {
PushDown(x);
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
PushDown(z); PushDown(y); PushDown(x);
int kind1 = x == ch[y][];
int kind2 = y == ch[z][];
if(z == goal) {
Rotate(x, kind1);
} else {
if(kind1 == kind2) Rotate(y, kind1);
else Rotate(x, kind1);
Rotate(x, kind2);
}
}
PushUp(x);
if(!goal) root = x;
} void RTO(int k, int goal) {
int x = root;
PushDown(x);
while(sz[lson] + != k) {
if(sz[lson] >= k) x = lson;
else k -= sz[lson] + , x = rson;
PushDown(x);
}
Splay(x, goal);
} void Travel(int x) {
if(lson) Travel(lson);
printf("travel : %d\n", x);
if(rson) Travel(rson);
PushUp(x);
} int Suf(int x) { // 找后继
if(rson) {
PushDown(x);
x = rson;
while(lson) {
x = lson;
PushDown(x);
}
}
return x;
} int Query(int l, int r) {
Splay(r, ); // 把原来节点的位置旋转到root位置
int ans = sz[ch[root][]]; // 因为多了一个节点,所以不用+1
RTO(l, ); // 把第l个数的前一个旋到root
Splay(Suf(r), root); // 把后继旋到ch[root][1]
rev[keytree] ^= ; //区间翻转
return ans;
} }spy; bool cmp(const node &a, const node &b) {
if(a.val == b.val) return a.id < b.id;
return a.val < b.val;
} int main() {
int n;
while(scanf("%d", &n), n) {
spy.n = n;
for(int i = ; i <= n; i++) {
scanf("%d", &spy.num[i]);
a[i].id = i;
a[i].val = spy.num[i];
}
sort(a + , a + + n, cmp);
spy.Init();
for(int i = ; i <= n; i++) {
int ans;
ans = spy.Query(i, a[i].id);
if(i == n) printf("%d\n", ans);
else printf("%d ", ans);
}
}
return ;
}

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

  1. HDU 1890 Robotic Sort(splay)

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

  2. HDU 1890 Robotic Sort (splay tree)

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

  3. HDU 4635:Strongly connected(强连通)

    http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给出n个点和m条边,问最多能添加几条边使得图不是一个强连通图.如果一开始强连通就-1.思路:把图分成 ...

  4. HDU 5775:Bubble Sort(树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=5775 Bubble Sort Problem Description   P is a permutation ...

  5. HDU 3487 Play with Chain(Splay)

    题目大意 给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作 操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数 ...

  6. BZOJ 1588:营业额统计(Splay)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1588 题意:中文题意. 思路:每一个点每一个点插入Splay,然后插入新的一个点之后,查这个节点的前 ...

  7. HDU 2767:Proving Equivalences(强连通)

    http://acm.hdu.edu.cn/showproblem.php?pid=2767 题意:给出n个点m条边,问在m条边的基础上,最小再添加多少条边可以让图变成强连通.思路:强连通分量缩点后找 ...

  8. HDU 5876:Sparse Graph(BFS)

    http://acm.hdu.edu.cn/showproblem.php?pid=5876 Sparse Graph Problem Description   In graph theory, t ...

  9. HDU 2062:Subset sequence(思维)

    Subset sequence Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

随机推荐

  1. iOS 本地加载html登陆页面

    Html的代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  2. ECharts 在同一个页面添加多个图表 并 给图表绑定事件

      <!DOCTYPE html> <head> <meta charset="utf-8"> <title>ECharts< ...

  3. ios判断点击的坐标点

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *allTouches = [event allTouc ...

  4. PostgreSQL中美元符号引用的字符串常量

    虽然用于指定字符串常量的标准语法通常都很方便,但是当字符串中包含了很多单引号或反斜线时很难理解它,因为每一个都需要被双写.要在这种情形下允许可读性更好的查询,PostgreSQL提供了另一种被称为“美 ...

  5. 免费VPN 实测可用

    vpngate.net 的镜像站点列表 (更新于 2014-05-18 03:06:00 UTC): http://121.135.220.121:26633/cn/ (Mirror location ...

  6. Codeforce Round #215 Div2 C

    还以为就这么点分了,不会跪了,起码有点加,生活都这么艰难了,为什么不让我好好地活下去! 是不是世界对我充满了恶意! 当然还是自己太菜! B题没初始化第一个就杯具了一次 C题大概的弄出来了,调了半个小时 ...

  7. 树形DP+RMQ+单调队列(Bob’s Race HDU4123)

    题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q, ...

  8. [原创]java WEB学习笔记58:Struts2学习之路---Result 详解 type属性,通配符映射

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. paper 8:支持向量机系列五:Numerical Optimization —— 简要介绍求解求解 SVM 的数值优化算法。

    作为支持向量机系列的基本篇的最后一篇文章,我在这里打算简单地介绍一下用于优化 dual 问题的 Sequential Minimal Optimization (SMO) 方法.确确实实只是简单介绍一 ...

  10. oracle冷备份后恢复

    本地恢复 在运行中输入cmd. 在cmd界面中输入sqlplus/nolog进入sql*plus. 以dba身份连接数据库conn sys/你设定的密码 as sysdba. 输入:shutdown ...