https://www.luogu.org/problemnew/solution/P3165

预处理

我们会发现一个问题:高度是无序的,而splay中要求有序,否则kth不能正确求解。
不需要求高度,只要求位置。
所以,用结构体存入 高度 与 下标,按高度排序,然后就可以把高度丢一边了(一波sao操作)。
记得头尾添加两个节点。。。
建树
正常 nlogn 可能会被卡常,所以,类似于线段树的建树,分此节点与左右儿子节点。
区间第k大
正常kth
区间翻转
首先,需要把所求的节点(即排序前下标为id的节点) splay 到 root 。
那么答案就是root左孩子的节点个数(因为有哨兵节点,所以+1-1抵消),记为s。
然后,取出 [i+1 , s+1] 这段区间,即:
将i节点 splay 到根,s+2节点 splay 到i的右节点。
再将s+2的左孩子打上翻转标记即可。

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 100010
#define MAX 999999999//最值
using namespace std;
int n,size=,root=;
struct node {
int x,id;
} b[MAXN];
namespace splay {
struct Splay {
int f,s,flag,son[];
int v;
} a[MAXN];
inline void clean(int rt) { //清空节点
a[rt].son[]=a[rt].son[]=a[rt].f=a[rt].s=a[rt].flag=a[rt].v=;
}
inline void pushup(int rt) { //上传
if(!rt)return;
a[rt].s=a[a[rt].son[]].s+a[a[rt].son[]].s+;
}
inline void pushdown(int rt) { //标记下传
if(!rt||!a[rt].flag)return;//记得这句
a[a[rt].son[]].flag^=;
a[a[rt].son[]].flag^=;
a[rt].flag^=;
swap(a[rt].son[],a[rt].son[]);
}
inline void turn(int rt,int k) { //旋转
int x=a[rt].f,y=a[x].f;
a[x].son[k^]=a[rt].son[k];
if(a[rt].son[k])a[a[rt].son[k]].f=x;
a[rt].f=y;
if(y)a[y].son[a[y].son[]==x]=rt;
a[x].f=rt;
a[rt].son[k]=x;
pushup(x);
pushup(rt);
}
void splay(int rt,int ancestry) { //伸展
while(a[rt].f!=ancestry) {
int x=a[rt].f,y=a[x].f;
pushdown(y);
pushdown(x);
pushdown(rt);//每次都要下传
if(y==ancestry)turn(rt,a[x].son[]==rt);
else {
int k=a[y].son[]==x?:;
if(a[x].son[k]==rt) {
turn(rt,k^);
turn(rt,k);
} else {
turn(x,k);
turn(rt,k);
}
}
}
if(ancestry==)root=rt;
}
inline int newnode(int x) { //建立新节点
int rt=size++;
clean(rt);
a[rt].v=x;
a[rt].s=;
return rt;
}
int buildtree(int l,int r) { //建树
if(l>r)return ;
int mid=l+r>>,lson=,rson=;
lson=buildtree(l,mid-);
int rt=newnode(b[mid].x);
rson=buildtree(mid+,r);
a[rt].son[]=lson;
a[rt].son[]=rson;
if(lson)a[lson].f=rt;
if(rson)a[rson].f=rt;
pushup(rt);//一定要有这句!
return rt;
}
int kth(int rt,int k) { //第k大值
if(a[rt].s<k)return ;
while() {
pushdown(rt);//下传
int y=a[rt].son[];
if(k>a[y].s+) {
k-=a[y].s+;
rt=a[rt].son[];
} else if(k<=a[y].s)rt=y;
else return rt;
}
}
inline void reverge(int i) { //区间翻转
splay(b[i].id+,);//记得加1(有哨兵节点)
int s=a[a[root].son[]].s;
printf("%d ",s);
int front=kth(root,i),next=kth(root,s+);
splay(front,);
splay(next,front);
a[a[next].son[]].flag^=;//打上标记
}
}
inline int read() {
int date=,w=;
char c=;
while(c<''||c>'') {
if(c=='-')w=-;
c=getchar();
}
while(c>=''&&c<='') {
date=date*+c-'';
c=getchar();
}
return date*w;
}
bool cmp(const node &x,const node &y) {
if(x.x==y.x)return x.id<y.id;
return x.x<y.x;
}
void init() { //预处理+读入+工作
n=read();
for(int i=; i<=n; i++) {
b[i].x=read();
b[i].id=i;
}
b[].x=-MAX;
b[].id=;
b[n+].x=MAX;
b[n+].id=n+;//两个哨兵节点
sort(b+,b+n+,cmp);
root=splay::buildtree(,n+);
for(int i=; i<=n-; i++)splay::reverge(i);
printf("%d\n",n);//最后一个一定是 n
}
int main() {
init();
return ;
}

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

  1. 【BZOJ3506】排序机械臂(Splay)

    [BZOJ3506]排序机械臂(Splay) 题面 神TMBZOJ没有题面,感谢SYC的题面 洛谷的题面也不错 题解 对于每次旋转的物体 显然可以预处理出来 现在只要模拟旋转操作就行了 至于在哪里放标 ...

  2. P3165 [CQOI2014]排序机械臂

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

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

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

  4. LibreOJ2241 - 「CQOI2014」排序机械臂

    Portal Description 给出一个\(n(n\leq10^5)\)个数的序列\(\{a_n\}\),对该序列进行\(n\)次操作.若在第\(i\)次操作前第\(i\)小的数在\(p_i\) ...

  5. 刷题总结:排序机械臂(石室中学oj)(splay)

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

  6. [bzoj1552\bzoj2506][Cqoi2014]robotic sort 排序机械臂_非旋转Treap

    robotic sort 排序机械臂 bzoj-1552 bzoj-2506 Cqoi-2014 题目大意:给定一个序列,让你从1到n,每次将[1,p[i]]这段区间反转,p[i]表示整个物品权值第i ...

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

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

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

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

  9. 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay

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

随机推荐

  1. THUSC2013

    魔塔 BZOJ 设每个敌人的属性值为\(hp_i,atk_i,def_i\).自己的为\(HP,ATK,DEF\) 首先我们可以发现顺序是没有影响的. 然后我们可以发现合适的\(ATK\)一定满足\( ...

  2. ES6——入门学习指南

    ES6的简介: ECMAScript6.0(以下简称ES6)是JavaScript语言的下一代标准,已在2015年6月正式发布了.它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序 ...

  3. linux 安装telnet

    一.CentOS下查看系统是否已安装telnet rpm -qa | grep telnet telnet 是挂在 xinetd 底下的,所以同时查看是否安装了xinetd服务 rpm -qa | g ...

  4. idea插件,配置

    1.插件 2.配置 1.去除double shift 全局搜索的功能,反正不符合我的习惯 Help -> Find Action  搜索 registry ,勾选 double.click.ha ...

  5. Scala学习二十二——定界延续

    一.本章要点 延续让你可以回到程序执行当中之前的某个点; 可以在shift块中捕获延续 延续函数一直延展到包含它的reset块的尾部 延续所谓的”余下的运算“,从包含shift的表达式开始,到包含它的 ...

  6. EFcore的 基础理解<二> shadow 特性

    接着上一篇.在MyEFTestContext 类中添加这个方法 protected override void OnModelCreating(ModelBuilder modelBuilder) { ...

  7. QT调用CHM方法

    QDesktopServices desktopServices;QString strUrl=QCoreApplication::applicationDirPath () ;strUrl=QStr ...

  8. git 分布式版本控制

    一.git版本控制 管理文件夹 安装省略 1. 进入要管理的文件夹 2. 初始化 (提名) 3. 管理 4. 生成版本 对应的命令: # 进入文件夹以后 右击选git bash here #初始化 g ...

  9. java-操作string的常用语法

    1.Java判断String是否以某个字符串开头: String mobile = "8618730600000";System.out.println(mobile.starts ...

  10. ASE2019 model组 事后诸葛亮会议记录

    诸葛亮文档 设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 传统编程教育模式下,初学者(主要是刚刚接触编程的学生)往往依靠老师与助教的课堂教学,由 ...