【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;
}
【BZOJ3506】[CQOI2014] 排序机械臂(Splay)的更多相关文章
- [BZOJ3506] [Cqoi2014] 排序机械臂 (splay)
Description 同OJ1552 Input Output Sample Input Sample Output HINT Source Solution Q:哎不是同一道题吗为什么分两篇博客来 ...
- bzoj3506 [Cqoi2014]排序机械臂
bzoj3506 此题是一道比较简单的spaly题目. 用splay维护序列,将每个点排到对应的位置之后删除,这样比较容易区间翻转. 我的指针写法在洛谷上AC了,但在bzoj上RE. #include ...
- BZOJ1552[Cerc2007]robotic sort&BZOJ3506[Cqoi2014]排序机械臂——非旋转treap
题目描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. 第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. 输出 输出共一行,N个用空格隔开 ...
- [bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂
非常垃圾的一道平衡树,结果被日了一天.很难受嗷嗷嗷 首先不得不说网上的题解让我这个本来就不熟悉平衡树的彩笔很难受——并不好理解. 还好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法. 题 ...
- 洛谷P3165 [CQOI2014]排序机械臂 Splay维护区间最小值
可以将高度定义为小数,这样就完美的解决了优先级的问题. Code: #include<cstdio> #include<algorithm> #include<cstri ...
- 【BZOJ3506】排序机械臂(Splay)
[BZOJ3506]排序机械臂(Splay) 题面 神TMBZOJ没有题面,感谢SYC的题面 洛谷的题面也不错 题解 对于每次旋转的物体 显然可以预处理出来 现在只要模拟旋转操作就行了 至于在哪里放标 ...
- P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 P1P_1P1 ,并把左起第一个物品至 P1P_1P1 ...
- 洛谷P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品 ...
- 【洛谷 P3165】 [CQOI2014]排序机械臂 (Splay)
题目链接 debug了\(N\)天没debug出来,原来是找后继的时候没有pushdown... 众所周知,,Splay中每个编号对应的节点的值是永远不会变的,因为所有旋转.翻转操作改变的都是父节点和 ...
随机推荐
- Car Flash ECU Programmer From autonumen
Whether you’re a home car owner or an auto mechanic — you can save thousands of dollars on car maint ...
- 关于处理百万级大批量数据的mysql运行几个重要点
处理大批量百万级的数据几点重要知识点: 一:设置php运行的内存配置 ini_set("memory_limit","1200M"); 在php.ini中有如下 ...
- 在新项目下使用rbc权限
例子说明: 8 个步骤 1. 拷贝rabc这个app到项目中 2. 把迁移过来的rbac下migrations记录删除 3. 把rabc注册到项目中 4. 创建数据库迁移 5. 注册admin,录入数 ...
- APP测试总结2
一.App测试流程与web项目流程区别 1.对UI要求比较高,需要更加注重用户体验.对于一个小小的屏幕,如何让用户使用更加轻便.简介.易用. 2.App是调用服务端接口展示数据.我们测试需要可以判断问 ...
- SpringBoot中使用Servlet
1.在入口Application类上加入注解@ServletComponentScan @SpringBootApplication @ServletComponentScan public clas ...
- spring 事务 @EnableTransactionManagement原理
@EnableXXX原理:注解上有个XXXRegistrar,或通过XXXSelector引入XXXRegistrar,XXXRegistrar实现了 ImportBeanDefinitionRegi ...
- jQuery源代码学习笔记_01
如何获取jQuery源代码 1.可以从GitHub上下载到没有合并和压缩的源代码 2.如果要查看兼容IE6-8的版本,请选择1.x-master分支 3.可以使用git clone也可以使用downl ...
- 根据时间显示不同的问候语的JavaScript代码
对于最近有许多的初学开发者问我关于根据时间显示不同的问候语的JavaScript代码问题,所以今天将自己整理的一些代码在这里分享出来,供初学者参考,如果在运行过程中有问题,可以给我在下方留言. < ...
- MS-DOS
MS-DOS doskey /history /reinstall /buffersize /macros doskey di=dir /w/p defrag 磁盘碎片整理 xcopy deltree ...
- 导入的项目eclipse出现乱码的处理方法
如果这样子还是出现乱码无法解决的话,则删掉当前项目重新开始项目.