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的边,终点往汇点连一个次 ...
随机推荐
- Android(java)学习笔记136:利用谷歌API对数据库增删改查(推荐使用)
接下来我们通过项目案例来介绍:这个利用谷歌API对数据库增删改查 1. 首先项目图: 2. 这里的布局文件activity_main.xml: <LinearLayout xmlns:andro ...
- VMware的centos的配置分区
/ ext3 8189 固定大小空 swap 509 固定大小/boot ext3 100 固定大小/home ext3 全部(使用全部可用空间) 利用的工具 AMFTP ...
- 洛谷 P1147 连续自然数和
洛谷 P1147 连续自然数和 看到dalao们的各种高深方法,本蒟蒻一个都没看懂... 于是,我来发一篇蒟蒻友好型的简单题解 #include<bits/stdc++.h> using ...
- 【Maven】 (请使用 -source 8 或更高版本以启用 lambda 表达式)
在使用mvn install编译maven项目时,报了 “ (请使用 -source 8 或更高版本以启用 lambda 表达式)”错误,是因为设置的maven默认jdk编译版本太低的问题. 可使用两 ...
- Linux中让alias设置永久生效的方法详解
Linux中让alias设置永久生效的方法详解 一.问题描述 1.有很多时候我们想要将很多操作作为一个步骤,那么在不作为系统的服务的情况下,别名是我们最好的选择,但是发现别名只能在一次会话中生效,重启 ...
- python3 输入某年某月某日,判断这一天是这一年的第几天?
题目 输入某年某月某日,判断这一天是这一年的第几天? 程序分析 特殊情况,闰年时需考虑二月多加一天. 代码: import calendar year = int(input("Year:& ...
- Lecture 1
Principles of GIS( UNSW Metternicht ) outline:data input---data management---data manipulation+data ...
- python标准输入输出
input() 读取键盘输入 input() 函数从标准输入读入一行文本,默认的标准输入是键盘. input 可以接收一个Python表达式作为输入,并将运算结果返回. print()和format( ...
- leetcode-10-basic
35. Search Insert Position Given a sorted array and a target value, return the index if the target i ...
- LeetCode(173) Binary Search Tree Iterator
题目 Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ...