【BZOJ3506】[CQOI2014] 排序机械臂(Splay)
点此看题面
大致题意: 给你\(n\)个数。第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推。求\(P_1,P_2,...,P_n\)的值。
关于洛谷上的四倍经验
这题在洛谷上是一道四倍经验题(目前看来是两黑两紫):
- 【洛谷3165】[CQOI2014] 排序机械臂
- 【洛谷4402】[CERC2007] robotic sort 机械排序
- 【SP2059】CERC07S - Robotic Sort
- 【UVA1402】Robotic Sort
初始化
这题应该是一道比较裸的\(Splay\)题。
首先,我们将原数组排序一遍,记下每一次操作的位置。
有一个细节,题目要求相同值要先取位置靠前的(没注意到这点结果狂\(WA\)不止)。
然后便是建树。
注意,\(Splay\)建树的过程中我们一般会在序列左右各加一个多余节点,方便后面取出一段区间进行操作。
操作
每一次操作,我们把要操作的位置先\(Splay\)到根,然后就可以得出答案即为此时左子树的\(Size\),记其为\(ans\)。
注意是\(Size\)而不是\(Size+1\),要考虑到我们在序列左边加的那个多余节点已经使\(Size\)比实际存在的节点个数多\(1\)了。
然后,按照题目要求,我们要翻转区间\([i,ans]\)。
直接将\(i\)号节点和\(ans+2\)号节点分别旋到根节点和根节点的右儿子,然后翻转根节点的右儿子的左儿子即可。
代码
#include<bits/stdc++.h>
#define Type template<typename I>
#define N 100000
#define swap(x,y) (x^=y^=x^=y)
#define INF 1e9
using namespace std;
int n;
struct Data
{int pos,val;inline friend bool operator < (Data x,Data y) {return x.val^y.val?x.val<y.val:x.pos<y.pos;}
}a[N+5];
class Class_FIO
{private:#define Fsize 100000#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)#define pc(ch) (FoutSize^Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,Fsize,stdout),Fout[(FoutSize=0)++]=ch))#define Isi(x) (typeid(x).name()==typeid(1).name())#define Isc(x) (typeid(x).name()==typeid('a').name())int Top,FoutSize;char ch,*A,*B,Fin[Fsize],Fout[Fsize],Stack[Fsize];public:Class_FIO() {A=B=Fin;}Type inline void read(I& x) {x=0;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));}Type inline void write(I x){if(Isi(x)) {while(Stack[++Top]=x%10+48,x/=10);while(Top) pc(Stack[Top--]);}if(Isc(x)) pc(x);}template<typename I,typename... A> inline void read(I& x,A&... y) {read(x),read(y...);}template<typename I,typename... A> inline void write(I x,A... y) {write(x),write(y...);}inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;}
}F;
class Class_Splay//Splay
{private:#define SIZE N#define PushUp(x) (node[x].Size=node[node[x].Son[0]].Size+node[node[x].Son[1]].Size+1)#define Rever(x) (swap(node[x].Son[0],node[x].Son[1]),node[x].Rev^=1)#define PushDown(x) (node[x].Rev&&(Rever(node[x].Son[0]),Rever(node[x].Son[1]),node[x].Rev=0))#define Which(x) (node[node[x].Father].Son[1]==x)#define Connect(x,y,d) (node[node[x].Father=y].Son[d]=x)#define Split(x,y) (Splay(get_pos(x),rt),Splay(get_pos((y)+2),node[rt].Son[1]),node[node[rt].Son[1]].Son[0])int rt;struct Tree{int Size,Rev,Father,Son[2];}node[SIZE+5];inline void Rotate(int x,int& k){register int fa=node[x].Father,pa=node[fa].Father,d=Which(x);PushDown(fa),PushDown(x),(fa^k?node[pa].Son[Which(fa)]=x:k=x),node[x].Father=pa,Connect(node[x].Son[d^1],fa,d),Connect(fa,x,d^1),PushUp(fa),PushUp(x);}inline void Splay(int x,int& k) {register int fa;while(x^k) fa=node[x].Father,fa^k&&(Rotate(Which(x)^Which(fa)?x:fa,k),0),Rotate(x,k);}inline void Build(int l,int r,int& rt){register int mid=l+r>>1;if(node[rt=mid].Size=1,!(l^r)) return;l<mid&&(Build(l,mid-1,node[rt].Son[0]),node[node[rt].Son[0]].Father=rt),r>mid&&(Build(mid+1,r,node[rt].Son[1]),node[node[rt].Son[1]].Father=rt),PushUp(rt);}inline int get_pos(int rk){register int x=rt;while(x) {if(PushDown(x),node[node[x].Son[0]].Size>=rk) x=node[x].Son[0];else if(!(rk-=node[node[x].Son[0]].Size+1)) return x;else x=node[x].Son[1];}}public:inline void Init(int len) {Build(1,len+2,rt);}inline int GetAns(int x) {register int k,ans;Splay(a[x].pos+1,rt),ans=node[node[rt].Son[0]].Size,k=Split(x,ans),Rever(k);//找到ans,然后翻转return ans;//返回答案}#undef SIZE
}Splay;
int main()
{register int i,p;for(F.read(n),i=1;i<=n;++i) F.read(a[a[i].pos=i].val);//读入for(sort(a+1,a+n+1),Splay.Init(n),i=1;i<=n;++i) F.write(p=Splay.GetAns(i),' ');//初始化排序+依次操作return F.clear(),0;
}
转载于:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3506.html
【BZOJ3506】[CQOI2014] 排序机械臂(Splay)相关推荐
- 洛谷3165 CQOI2014 排序机械臂 splay
题目链接 题意: 给你一个长度为nnn的序列,现在有一种对序列排序的方法:假设当前最小的前iii个已经找到了,我们找到i+1i+1i+1到nnn里面最早出现的最小值,设其出现位置为jjj,我们将区间[ ...
- [bzoj1552][Cerc2007]robotic sort[bzoj3506][Cqoi2014]排序机械臂
非常垃圾的一道平衡树,结果被日了一天.很难受嗷嗷嗷 首先不得不说网上的题解让我这个本来就不熟悉平衡树的彩笔很难受--并不好理解. 还好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法. 题 ...
- 【splay】BZOJ 1152 3506:[cqoi2014]排序机械臂
BZOJ 1152 && 3506:[cqoi2014]排序机械臂 Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,第二行为N个用空格隔开的正整数 ...
- bzoj 1552: [Cerc2007]robotic sort bzoj 3506: [Cqoi2014]排序机械臂(splay区间翻转)
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MB Submit: 1206 Solved: 460 [Submi ...
- P3165 [CQOI2014]排序机械臂
传送门 就是说要维护一个数据结构资瓷区间反转和查询第\(K\)大,那么splay吧 我们可以把原数组按高度为第一关键字,下标为第二关键字排序,然后直接建出splay 这样的话每次第\(K\)大直接查询 ...
- 【bzoj3506】【CQOI2014】排序机械臂
Description 有n个物品,每个物品有它的高度a[i],现在我们要采用一种神奇的方法把这n个物品排好序.第x次我们找到第x矮的物品位置p[x],并且把x到p[x]中间的物品翻转.如果有多个一样 ...
- python机械臂仿真_使用VTK与Python实现机械臂三维模型可视化
三维可视化系统的建立依赖于三维图形平台, 如 OpenGL.VTK.OGRE.OSG等, 传统的方法多采用OpenGL进行底层编程,即对其特有的函数进行定量操作, 需要开发人员熟悉相关函数, 从而造成 ...
- 简单的机械臂设计(Splay树)
时间限制: 2 Sec 内存限制: 32 MB 题目描述 在东秦综合楼的深处,有实验室检查各种材料的机械和电学性能.你受蔡老板所托为一个在实验室中处理样品的机器人编写软件.在传送带上有材料样本,样品有 ...
- 机器人抓矸石_基于机器视觉的多机械臂煤矸石分拣机器人系统研究
工矿自动化 Industryand MineAutomation Vol. 45 No. 9 Sep.2019 第 45 卷第 9 期 2019 年 9 月 文章编号 : 1671 - 251X(20 ...
最新文章
- 在外壳中获取程序执行时间
- java 判断pc还是手机_java-判断是移动端还是PC端访问
- python和表格关系_数据表之多表关联
- x86上的Java最终字段没有操作?
- 再送一波干货,测试2000线程并发下同时查询1000万条数据库表及索引优化
- 便携式计算机推销洽谈方案,推销洽谈的方法
- NHibernet能带来什么呢?
- C语言文件的存储和处理实验报告,c语言文件处理实验报告(6页)-原创力文档...
- LTE基本结构(常见接口)
- Python-Cartopy制图学习02-中国2010年5月干旱情况空间制图
- 如何快速开通流量主,提升小程序UV访客
- 如何打开.exe文件
- matlab 边缘检测 抠图,ps如何调整边缘的流程:边缘检测、调整边缘、输出(调整边缘抠图...
- 基于java火车购票系统
- 【画方】画方网络准入管理系统
- 阻塞队列(一):ArrayBlockingQueue
- 时隔27年,微软IE浏览器正式退出历史舞台,一个时代的结束
- 在 TortoiseGit 中使用 stash 操作---暂存操作、部分提交
- 头疼的动态规划:跳木板
- oracle 10g oci.dll 下载,oci.dll oracle 下载