题目描述

输入

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

输出

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

样例输入

6
3 4 5 1 6 2

样例输出

4 6 4 5 6 6


题解

splay

先将原数据从小到大排序,类似于离散化,把它们的排名存入splay中。

那么第k小的数的数组下标就是k。

区间反转即可。

#include <cstdio>
#include <algorithm>
#define N 100005
using namespace std;
struct data
{
int num , pos;
}a[N];
int c[2][N] , fa[N] , tag[N] , si[N] , id[N] , root;
bool cmp(data a , data b)
{
return a.num == b.num ? a.pos < b.pos : a.num < b.num;
}
void pushup(int k)
{
si[k] = si[c[0][k]] + si[c[1][k]] + 1;
}
void pushdown(int k)
{
if(tag[k])
{
swap(c[0][c[0][k]] , c[1][c[0][k]]);
swap(c[0][c[1][k]] , c[1][c[1][k]]);
tag[c[0][k]] ^= 1;
tag[c[1][k]] ^= 1;
tag[k] = 0;
}
}
void build(int l , int r , int f)
{
if(l > r) return;
int mid = (l + r) >> 1;
build(l , mid - 1 , mid);
build(mid + 1 , r , mid);
fa[id[mid]] = id[f];
c[mid > f][id[f]] = id[mid];
pushup(id[mid]);
}
void rotate(int &k , int x)
{
int y = fa[x] , z = fa[y] , l , r;
l = (c[0][y] != x);
r = l ^ 1;
if(y == k) k = x;
else if(c[0][z] == y) c[0][z] = x;
else c[1][z] = x;
fa[x] = z;
fa[y] = x;
fa[c[r][x]] = y;
c[l][y] = c[r][x];
c[r][x] = y;
pushup(y);
pushup(x);
}
void splay(int &k , int x)
{
while(x != k)
{
int y = fa[x] , z = fa[y];
if(y != k)
{
if(c[0][y] == x ^ c[0][z] == y) rotate(k , x);
else rotate(k , y);
}
rotate(k , x);
}
}
int getrank(int x)
{
if(x == root) return si[c[0][x]] + 1;
int r = getrank(fa[x]);
pushdown(x);
if(x == c[0][fa[x]]) r -= si[c[1][x]] + 1;
else r += si[c[0][x]] + 1;
return r;
}
int find(int k , int x)
{
pushdown(k);
if(x <= si[c[0][k]]) return find(c[0][k] , x);
else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
else return k;
}
int main()
{
int n , i;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d" , &a[i].num);
a[i].pos = i;
}
sort(a + 1 , a + n + 1 , cmp);
for(i = 1 ; i <= n ; i ++ )
id[a[i].pos + 1] = i;
id[1] = n + 1;
id[n + 2] = n + 2;
build(1 , n + 2 , 0);
root = id[(n + 3) >> 1];
for(i = 1 ; i <= n ; i ++ )
{
int ri = getrank(i) , tx , ty;
printf("%d%c" , ri - 1 , i == n ? '\n' : ' ');
tx = find(root , i);
ty = find(root , ri + 1);
splay(root , tx);
splay(c[1][root] , ty);
swap(c[0][c[0][c[1][root]]] , c[1][c[0][c[1][root]]]);
tag[c[0][c[1][root]]] ^= 1;
}
return 0;
}

【bzoj1552】[Cerc2007]robotic sort的更多相关文章

  1. 【BZOJ1552】[Cerc2007]robotic sort Splay

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

  2. 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值

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

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

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

  4. 【HDOJ】1890 Robotic Sort

    伸展树伤不起啊,很容易wa,很容易T,很容易M. /* 1890 */ #include <iostream> #include <string> #include <m ...

  5. BZOJ1552/3506 [Cerc2007]robotic sort

    Splay 与之前不同的是如果你仅仅是翻转左右区间的话可以在find里面做因为对他有影响的子树在做之前一定在他的上面从上到下搜索的过程可以把rever做了. 但这道题要求我们输出转换之前的,因此不能保 ...

  6. [BZOJ1552][Cerc2007]robotic sort

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

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

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

  8. bzoj 1552: [Cerc2007]robotic sort

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

  9. 【LeetCode】147. Insertion Sort List 解题报告(Python)

    [LeetCode]147. Insertion Sort List 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...

随机推荐

  1. java跳过构造方法新建对象

    Java有四种创建对象的方法: (1) 用new语句创建对象,这是最常见的创建对象的方法. (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constr ...

  2. Android OpenGL ES(十四)gl10方法解析

    Android 支持 OpenGL 列表 1.GL 2.GL 10 3.GL 10 EXT 4.GL 11 5.GL 11 EXT 6.GL 11 ExtensionPack 我们将使用 GL10 这 ...

  3. THOUGHTS: programming in linux... with third_party open sources... methods

    Actually I do not have experiences in programming with open sources/third party libs.. in linux.. I ...

  4. HDU 5833 (2016大学生网络预选赛) Zhu and 772002(高斯消元求齐次方程的秩)

    网络预选赛的题目……比赛的时候没有做上,确实是没啥思路,只知道肯定是整数分解,然后乘起来素数的幂肯定是偶数,然后就不知道该怎么办了… 最后题目要求输出方案数,首先根据题目应该能写出如下齐次方程(从别人 ...

  5. android sql Cursor

    Cursor 是每行的集合. 使用 moveToFirst() 定位第一行. 你必须知道每一列的名称.你必须知道每一列的数据类型.Cursor 是一个随机的数据源. 所有的数据都是通过下标取得. Cu ...

  6. Windows Batch Scripts

    Some simple examples: simple.bat @echo off set _var1=3 set _var2=5 set /a _result=%_var1%+%_var2% ec ...

  7. Struts的前世今身

    1.Struts1的运行原理 a.初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的Servlet,在启动时总控制器会读取配置文件( ...

  8. dotnet core error 0x80070057

    安装补丁KB2533623 https://support.microsoft.com/en-us/kb/2533623

  9. angular实现select的ng-options

    html <div ng-controller="ngSelect"> <select ng-model="vm.selectVal" ng- ...

  10. Windows Server 2003 下如何安装及配置 FTP 服务器(转)

    Windows Server 2003 下如何安装及配置 FTP 服务器 一.安装 FTP 服务器组件: 写在这里的一点 : 安装及配置 FTP 服务器之前 , 必须先手工配置服务器本身的 IP 地址 ...