LibreOJ2241 - 「CQOI2014」排序机械臂
Description
给出一个\(n(n\leq10^5)\)个数的序列\(\{a_n\}\),对该序列进行\(n\)次操作。若在第\(i\)次操作前第\(i\)小的数在\(p_i\)位置,则翻转区间\([i,p_i]\)。易知\(n\)次操作后序列会变为升序。求出每一次的\(p_i\)。
Solution
splay。
题里的\(a_i\)是会重复的...所以先离散化一波,相同的数按位置排名。然后根据初始位置建一棵splay,每次将\(i\)旋转到根求左子树大小即可,区间翻转用splay也很好实现。注意翻转需要加入在序列头尾加入两个哨兵节点。
时间复杂度\(O(nlogn)\)。
Code
//「CQOI2014」排序机械臂
#include <algorithm>
#include <cstdio>
using std::sort;
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
inline void swap(int &x,int &y) {int t; t=x,x=y,y=t;}
const int N=2e5+10;
int n,a[N];
int rt,fa[N],ch[N][2],siz[N]; bool rev[N];
int wh(int p) {return p==ch[fa[p]][1];}
void update(int p) {siz[p]=siz[ch[p][0]]+1+siz[ch[p][1]];}
void rever(int p) {rev[p]^=1; swap(ch[p][0],ch[p][1]);}
void pushdw(int p) {if(rev[p]) rever(ch[p][0]),rever(ch[p][1]),rev[p]=false;}
void rotate(int p)
{
int q=fa[p],r=fa[q],w=wh(p);
fa[p]=r; if(r) ch[r][wh(q)]=p;
fa[ch[q][w]=ch[p][w^1]]=q;
fa[ch[p][w^1]=q]=p;
update(q),update(p);
}
void pushdwRt(int p) {if(fa[p]) pushdwRt(fa[p]); pushdw(p);}
void splay(int p,int &k)
{
pushdwRt(p); int t=fa[k];
for(int q=fa[p];q!=t;rotate(p),q=fa[p]) if(fa[q]!=t) rotate(wh(p)^wh(q)?p:q);
update(k=p);
}
void bldTr(int &p,int L0,int R0)
{
if(L0>R0) return;
int mid=L0+R0>>1; p=a[mid];
bldTr(ch[p][0],L0,mid-1),bldTr(ch[p][1],mid+1,R0);
fa[ch[p][0]]=fa[ch[p][1]]=p; update(p);
}
int rnk(int x)
{
int p=rt;
while(true)
{
pushdw(p);
if(x<=siz[ch[p][0]]) p=ch[p][0];
else if(x==siz[ch[p][0]]+1) return p;
else x-=siz[ch[p][0]]+1,p=ch[p][1];
}
}
void split(int x,int y)
{
int p=rnk(x-1),q=rnk(y+1);
splay(p,rt),splay(q,ch[rt][1]);
}
struct rec{int x,id;} tmp[N];
bool cmpX(rec a,rec b) {return a.x==b.x?a.id<b.id:a.x<b.x;}
void discrete()
{
for(int i=1;i<=n;i++) tmp[i].x=a[i],tmp[i].id=i;
sort(tmp+1,tmp+n+1,cmpX);
for(int i=1;i<=n;i++) a[tmp[i].id+1]=i+1;
a[1]=1,a[n+2]=n+2;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
discrete(); bldTr(rt,1,n+2);
for(int i=2;i<=n+1;i++)
{
splay(i,rt); int x=siz[ch[rt][0]]+1;
printf("%d ",x-1);
split(i,x),rever(ch[ch[rt][1]][0]);
}
return 0;
}
LibreOJ2241 - 「CQOI2014」排序机械臂的更多相关文章
- 【BZOJ】【1552】【Cerc2007】robotic sort / 【3506】【CQOI2014】排序机械臂
Splay 离散化+Splay维护序列…… 好吧主要说一下我做这道题遇到的几个错误点: 1.离散化 2.由于找到的这个数的位置一定是大于等于 i 的,所以其实在把它splay到根以后,i 结点只能sp ...
- 【BZOJ3506】【Cqoi2014】排序机械臂
传送门(因为BZOJ上没有题面...所以放的是luogu的) 题意:你需要维护一个序列,支持区间翻转与查询区间最小. 解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解 ...
- 【BZOJ3506】[CQOI2014] 排序机械臂(Splay)
点此看题面 大致题意: 给你\(n\)个数.第一次找到最小值所在位置\(P_1\),翻转\([1,P_1]\),第二次找到剩余数中最小值所在位置\(P_2\),翻转\([2,P_2]\),以此类推.求 ...
- [bzoj1552\bzoj2506][Cqoi2014]robotic sort 排序机械臂_非旋转Treap
robotic sort 排序机械臂 bzoj-1552 bzoj-2506 Cqoi-2014 题目大意:给定一个序列,让你从1到n,每次将[1,p[i]]这段区间反转,p[i]表示整个物品权值第i ...
- P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 P1P_1P1 ,并把左起第一个物品至 P1P_1P1 ...
- 洛谷P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品 ...
- 【BZOJ3506】排序机械臂(Splay)
[BZOJ3506]排序机械臂(Splay) 题面 神TMBZOJ没有题面,感谢SYC的题面 洛谷的题面也不错 题解 对于每次旋转的物体 显然可以预处理出来 现在只要模拟旋转操作就行了 至于在哪里放标 ...
- 刷题总结:排序机械臂(石室中学oj)(splay)
题目: 题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到最低的物品位置 P1,并把从左起第 1 个至第 P1 个之间的物品反序 ...
- 【LOJ】#2239. 「CQOI2014」危桥
LOJ#2239. 「CQOI2014」危桥 就是先把每条边正着连一条容量为2的边,反着连一条容量为2的边 显然如果只有一个人走的话,答案就是一个源点往起点连一条容量为次数×2的边,终点往汇点连一个次 ...
随机推荐
- 【UML】概述
前言 看完UML视频,很多人不明白UML到底是干什么用的,举个通俗的例子,就像盖房子一样,厨房卧室楼层之间怎么拼接,每个部分用什么材料,每个部分里放什么家具什么餐具,每个部分是干吗用的,UML就相当于 ...
- Netbackup常用命令--bpdbjobs
1.大纲 bpdbjobs – 与 NetBackup 作业数据库进行交互 bpdbjobs [-report] [-M master_servers] [-ignore_parent_jobs] [ ...
- Java的数组与内存控制
1 数组基础 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成.其中,每一个数据称作一个数组元素(item),每个数组元素可以通过一个下标/索引来(index)访问它们. 数组 ...
- [论文理解]Region-Based Convolutional Networks for Accurate Object Detection and Segmentation
Region-Based Convolutional Networks for Accurate Object Detection and Segmentation 概括 这是一篇2016年的目标检测 ...
- MFC:Unicode和多字节字符集下 CString和char的转化(MFC中)
2011-05-16 00:10 1166人阅读 评论(0) 收藏 举报 mfcdelete Unicode下 CString转TCHAR TCHAR* szMsg = new TCHAR[wcsle ...
- AddDbContext was called with configuration, but the context type 'NewsContext' only declares a parameterless constructor?
问题 An error occurred while starting the application. ArgumentException: AddDbContext was called with ...
- java 第11次作业:你能看懂就说明你理解了——this关键字
this 代表当前对象
- 解决升级mac os X EI Capitan后遇到LibclangError: dlopen(libclang.dylib, 6): image not found.的问题
打开文件./frameworks/cocos2d-x/tools/bindings-generator/clang/cindex.py 把第 3395 行 改为 : library = cdll.Lo ...
- 【转】MFC编辑框自动换行,垂直滚动条自动下移
1.新建一个编辑框控件(Edit Control),将其多行(Multiline)前面打勾(属性设置为True),Auto HScroll前面的勾去掉(属性设置False),这样就可以实现每一行填满后 ...
- 对象、句柄、ID之间的区别
对象是C++的概念,C++的类对象 句柄是Windows SDK的概念,指向某种资源的一种“指针”(有时候底层不一定是指针) 资源ID在MFC里仅仅是一个宏,也就是个整数. 其实,句柄是控件在数据结构 ...