题目描述

为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 P1P_1P1​ ,并把左起第一个物品至 P1P_1P1​ 间的物品 (即区间 [1,P1][1,P_1][1,P1​] 间的物品) 反序;第二次找到第二低的物品的位置 P2P_2P2​ ,并把左起第二个至 P2P_2P2​ 间的物品 (即区间 [2,P2][2,P_2][2,P2​] 间的物品) 反序……最终所有的物品都会被排好序。

上图给出有六个物品的示例,第一次操作前,高度最低的物品在位置 444 ,于是把第一至第四的物品反序;第二次操作前,第二低的物品在位罝六,于是把第二至六的物品反序……

你的任务便是编写一个程序,确定一个操作序列,即每次操作前第 iii 低的物品所在位置 PiP_iPi​ ,以便机械臂工作。需要注意的是,如果有高度相同的物品,必须保证排序后它们的相对位置关系与初始时相同。

输入输出格式

输入格式:

第一行包含正整数n,表示需要排序的物品数星。

第二行包含n个空格分隔的整数PiP_iPi​,表示每个物品的高度。

输出格式:

输出一行包含n个空格分隔的整数Pi。

输入输出样例

输入样例#1:

6
3 4 5 1 6 2
输出样例#1:

4 6 4 5 6 6

说明

N<=100000

Pi<=10^7

Solution:

  本题既然区间反转,那么Splay裸题。

  首先对高度排序得到操作的顺序,再对初始位置中序遍历建树。

  对于每次操作的原位置,将其旋到根,答案(新的位置)就是其左子树的大小,然后因为它的前趋之前的数已经位置固定,那么只要把它和后继所在的子树翻转,所以把前趋旋转到根,再把后继旋转到根的右儿子,打上懒惰标记就好了。

  注意,每次在splay改变树的形态时下放标记,用栈存下一条链上的节点并下放,在查排名的时候也得下放标记。

代码:

/*Code by 520 -- 9.20*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
#define son(x) (x==ch[fa[x]][1])
using namespace std;
const int N=;
int n,ans,stk[N],top;
int root,cnt,ch[N][],siz[N],lazy[N],fa[N];
struct node{
int v,id;
bool operator < (const node &a) const {return v==a.v?id<a.id:v<a.v;}
}a[N]; int gi(){
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-') x=getchar();
if(x=='-') x=getchar(),f=;
while(x>=''&&x<='') a=(a<<)+(a<<)+(x^),x=getchar();
return f?-a:a;
} il void pushup(int rt){siz[rt]=siz[ch[rt][]]+siz[ch[rt][]]+;} il void pushdown(int rt){
if(lazy[rt]){
lazy[ch[rt][]]^=,lazy[ch[rt][]]^=;
swap(ch[rt][],ch[rt][]),lazy[rt]=;
}
} il void rotate(int x){
int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
z?ch[z][c]=x:root=x; fa[x]=z;
if(a) fa[a]=y; ch[y][b]=a;
fa[y]=x,ch[x][!b]=y;
pushup(y),pushup(x);
} il void splay(int x,int i){
int tp=x;top=;
while(fa[tp]!=i) stk[++top]=tp,tp=fa[tp];
while(top) pushdown(stk[top--]);
while(fa[x]!=i){
int y=fa[x],z=fa[y];
if(z==i) rotate(x);
else {
if(son(x)==son(y)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
} int build(int l,int r,int lst){
int rt=l+r>>;
fa[rt]=lst,siz[rt]=;
if(l<rt) ch[rt][]=build(l,rt-,rt);
if(r>rt) ch[rt][]=build(rt+,r,rt);
pushup(rt);return rt;
} il int getrank(int x){
int rt=root;
while(){
pushdown(rt);
if(siz[ch[rt][]]>=x&&ch[rt][]) rt=ch[rt][];
else {
x-=siz[ch[rt][]]+;
if(!x) return rt;
rt=ch[rt][];
}
}
} int main(){
n=gi();
a[]={-0x7fffffff,},a[n+]={0x7fffffff,n+};
For(i,,n+) a[i].v=gi(),a[i].id=i;
sort(a+,a+n+);
root=build(,n+,);
For(i,,n) {
splay(a[i].id,);
ans=siz[ch[root][]]+;
printf("%d ",ans-);
int pre=getrank(i-),suc=getrank(ans+);
splay(pre,),splay(suc,pre);
lazy[ch[ch[root][]][]]^=;
}
printf("%d",n);
return ;
}

P3165 [CQOI2014]排序机械臂的更多相关文章

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

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

  2. Luogu P3165 [CQOI2014]排序机械臂

    先讲一下和这题一起四倍经验的题: Luogu P4402 [Cerc2007]robotic sort 机械排序 SP2059 CERC07S - Robotic Sort UVA1402 Robot ...

  3. [UVA1402]Robotic Sort;[SP2059]CERC07S - Robotic Sort([洛谷P3165][CQOI2014]排序机械臂;[洛谷P4402][Cerc2007]robotic sort 机械排序)

    题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成.输出每次操作的$P_ ...

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

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

  5. 【BZOJ3506】[CQOI2014] 排序机械臂(Splay)

    点此看题面 大致题意: 给你\(n\)个数.第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推.求 ...

  6. 【洛谷 P3165】 [CQOI2014]排序机械臂 (Splay)

    题目链接 debug了\(N\)天没debug出来,原来是找后继的时候没有pushdown... 众所周知,,Splay中每个编号对应的节点的值是永远不会变的,因为所有旋转.翻转操作改变的都是父节点和 ...

  7. BZOJ1552[Cerc2007]robotic sort&BZOJ3506[Cqoi2014]排序机械臂——非旋转treap

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

  8. bzoj3506 [Cqoi2014]排序机械臂

    bzoj3506 此题是一道比较简单的spaly题目. 用splay维护序列,将每个点排到对应的位置之后删除,这样比较容易区间翻转. 我的指针写法在洛谷上AC了,但在bzoj上RE. #include ...

  9. BZOJ3506/1502 [CQOI2014]排序机械臂

    传送门 依然是一道splay的区间操作,需要注意的是要把下标离散化后来表示splay的节点,我不知道怎么搞所以索性弄了个$ValuetoNode$,看样子没什么问题, 感觉他那个传下标的方法太暴力了. ...

随机推荐

  1. 在Telnet中用FTP传输文件

    如果用 Telnet 传输文件? 在自己的机子上架设FTP服务器,然后登陆远程机后,就可以登录自己的FTP.利用PUT(上传命令),就可以把远程电脑的文件下载下来.     如果出现连接不上FTP,也 ...

  2. A* 寻路的八个变种

    变种 1 - 束搜索(Beam Search) 在 A* 算法的住循环中,OPEN 集存储可能需要搜索的节点,用来以查找路径. 束搜索是 A* 的变体,它限制了OPEN集的大小. 如果集合变得太大,则 ...

  3. 六边形地图Cube coordinates理解

    1.这个是 Axial coordinates,可以实现六边形4个方向上的移动 2.但是六边形还有两个方向需要移动,所以引入了Cube coordinates,这个坐标系多了一个轴向,Y轴,X轴沿水平 ...

  4. java多线程之述解

    说起线程 就不得不提进程 他们之间的关系很紧密 进程:内存中运行的应用程序 每个进程都有自己的一块内存空间 而线程是进程中的一个执行单元 一个进程中可以有多个线程 多线程的好处就是可以并发操作程序 将 ...

  5. 编码 解码 python

    之前一直对python文件中编码解码糊里糊涂,今天看到一篇文章,觉得把我讲的有点明白了.写个心得吧. 1.编码解码是怎么一回事? Python 里面的编码和解码也就是 unicode 和 str 这两 ...

  6. yocto-sumo源码解析(八): ProcessServer

    从前面章节的论述中,我们知道BitBakeServer实际上是一个ProcessServer,什么是ProcessServer不可不了解. 1. 类的声明: 首先这是一个python的多进程包里面的进 ...

  7. 【LDAP安装】在已编译安装的PHP环境下安装LDAP模块

    在已编译安装的PHP环境下安装LDAP模块 (乐维温馨提示:其他模块也能以这个方式安装) 1.在PHP源码包内找到ldap模块文件 cd php-5.6.37 cd ext/ldap/ 2.phpiz ...

  8. gulp: Did you forget to signal async completion? 解决方案

    背景 学习gulp的前端自动化构建,按照示例代码,跑了一个简单的task,控制台打出如下提示: The following tasks did not complete: testGulp Did y ...

  9. DenseNet——Densely Connected Convolutional Networks

    1. 摘要 传统的 L 层神经网络只有 L 个连接,DenseNet 的结构则有 L(L+1)/2 个连接,每一层都和前面的所有层进行连接,所以称之为密集连接的网络. 针对每一层网络,其前面所有层的特 ...

  10. [转载]GB2312简体中文编码表

    编码表源地址:http://www.knowsky.com/resource/gb2312tbl.htm编码在线查询:http://www.qqxiuzi.cn/bianma/zifuji.phpGB ...