Portal

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」排序机械臂的更多相关文章

  1. 【BZOJ】【1552】【Cerc2007】robotic sort / 【3506】【CQOI2014】排序机械臂

    Splay 离散化+Splay维护序列…… 好吧主要说一下我做这道题遇到的几个错误点: 1.离散化 2.由于找到的这个数的位置一定是大于等于 i 的,所以其实在把它splay到根以后,i 结点只能sp ...

  2. 【BZOJ3506】【Cqoi2014】排序机械臂

    传送门(因为BZOJ上没有题面...所以放的是luogu的) 题意:你需要维护一个序列,支持区间翻转与查询区间最小. 解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解 ...

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

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

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

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

  5. P3165 [CQOI2014]排序机械臂

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

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

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

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

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

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

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

  9. 【LOJ】#2239. 「CQOI2014」危桥

    LOJ#2239. 「CQOI2014」危桥 就是先把每条边正着连一条容量为2的边,反着连一条容量为2的边 显然如果只有一个人走的话,答案就是一个源点往起点连一条容量为次数×2的边,终点往汇点连一个次 ...

随机推荐

  1. GWT module 'xxx' may need to be (re)compiled解决办法

    使用GWT Eclipse Plug-in开发GWT应用,启动程序,在浏览器地址栏中输入http://127.0.0.1:8888/HelloWorld.html,没有出现我所期望的结果,而是弹出如下 ...

  2. 查询linux文件的MD5值

    Linux下查询文件的MD5值:md5sum xxx.iso.md5 MD5算法常常被用来验证网络文件传输的完整性,防止文件被人篡改.MD5全称是报文摘要算法(Message-Digest Algor ...

  3. cocos2dx 3.x c++代码打包给lua调用过程(mac)

    下载cocos2dx 框架,在应用程序->cocos->framework->cocos2d-x-3.x->tools->tolua目录下,一个ini文件对应一个py文件 ...

  4. C++ 学习笔记(二) const的加强

    const 含义为只读.如果在程序中显式改变const变量那么编译会报错. C语言的const: 在C语言中const 变量是放在内存中,如果使用指针可以间接改变const变量.所以在C语言中cons ...

  5. C++ Primer读书笔记(一)第一篇:C++概述,第一章:开始

    1. 主要内容 介绍程序语言的核心思想和C++的基本概念. 印象比较深刻的就是分而治之(divide and conque)的分解思想. 2. 知识广场 1) C++ 文件后缀 cc, cpp,,cx ...

  6. Inkscape基础

    What is Inkscape A program for creating vector graphics For Windows, Mac OS, and Linux Open source F ...

  7. python入门:py2.x里面除法或乘法这么写就可以计算小数点后面结果

    #!/usr/bin/env python # -*- coding:utf-8 -*- #py2.x里面除法或乘法这么写就可以计算小数点后面结果,更精确future(未来,译音:非忧车) divis ...

  8. CentOS 6 搭建SVN支持httpd和svnserve独立服务器两种模式 以及邮件配置

    Linux下SVN服务器同时支持Apache的http和svnserve独立服务器两种模式且使用相同的访问权限账号 服务器操作系统:CentOS 6.x 1.在服务器上安装配置SVN服务: 2.配置S ...

  9. 【android】android对位图文件的支持

    Android 支持以下三种格式的位图文件:.png(首选)..jpg(可接受)..gif(不建议).

  10. python的标准模块

    本文用于记录python中的标准模块,随时更新. decimal模块(解决小数循环问题): >>> import decimal >>> a = decimal.D ...