题目描述

输入

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。
第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

输出

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 
注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

样例输入

6
3 4 5 1 6 2

样例输出

4 6 4 5 6 6
 
非旋转treap练习题。题目要求每次找到第i小的Pi并将i~Pi翻转,因为在第i次操作时,前i小的数在最前面不会被翻转,之后也不会被用到。那么我们可以对序列建非旋转treap每次找到最小的,然后删除掉它,再将它原位置之前的部分翻转即可。但发现不能只维护子树最小值,因为有相同值时要选编号小的,也不能有多个最小值优先遍历左子树,因为原先编号小的翻转后可能成了右子树。所以我们先将原序列排个序,按排序后的顺序作为他们新的权值,再按原顺序插入treap,这样每个点的权值就是独一无二的了,直接记录最小值每次查找即可。不要忘记查找时也要下传翻转标记。

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n;
int cnt;
int root;
int x,y,z;
int v[100010];
int s[100010];
int r[100010];
int mn[100010];
int ls[100010];
int rs[100010];
int size[100010];
struct miku
{
int val;
int num;
int rak;
}a[100010];
bool cmp1(miku a,miku b)
{
if(a.val!=b.val)
{
return a.val<b.val;
}
return a.num<b.num;
}
bool cmp2(miku a,miku b)
{
return a.num<b.num;
}
int build(int val)
{
int rt=++cnt;
r[rt]=rand();
v[rt]=val;
mn[rt]=val;
size[rt]=1;
return rt;
}
void rotate(int rt)
{
swap(ls[rt],rs[rt]);
s[rt]^=1;
}
void pushup(int rt)
{
size[rt]=size[ls[rt]]+size[rs[rt]]+1;
mn[rt]=v[rt];
if(ls[rt])
{
mn[rt]=min(mn[rt],mn[ls[rt]]);
}
if(rs[rt])
{
mn[rt]=min(mn[rt],mn[rs[rt]]);
}
}
void pushdown(int rt)
{
if(s[rt])
{
if(ls[rt])
{
rotate(ls[rt]);
}
if(rs[rt])
{
rotate(rs[rt]);
}
s[rt]^=1;
}
}
int merge(int x,int y)
{
if(!x||!y)
{
return x+y;
}
pushdown(x);
pushdown(y);
if(r[x]<r[y])
{
rs[x]=merge(rs[x],y);
pushup(x);
return x;
}
else
{
ls[y]=merge(x,ls[y]);
pushup(y);
return y;
}
}
void split(int rt,int k,int &x,int &y)
{
if(!rt)
{
x=y=0;
return ;
}
pushdown(rt);
if(size[ls[rt]]<k)
{
x=rt;
split(rs[rt],k-size[ls[rt]]-1,rs[x],y);
}
else
{
y=rt;
split(ls[rt],k,x,ls[y]);
}
pushup(rt);
}
int rank(int rt)
{
pushdown(rt);
int res=v[rt];
if(ls[rt])
{
res=min(res,mn[ls[rt]]);
}
if(rs[rt])
{
res=min(res,mn[rs[rt]]);
}
if(res==mn[ls[rt]])
{
return rank(ls[rt]);
}
else if(res==v[rt])
{
return size[ls[rt]]+1;
}
else
{
return size[ls[rt]]+1+rank(rs[rt]);
}
}
int main()
{
srand(20020419);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].num=i;
}
sort(a+1,a+1+n,cmp1);
for(int i=1;i<=n;i++)
{
a[i].rak=i;
}
sort(a+1,a+1+n,cmp2);
for(int i=1;i<=n;i++)
{
root=merge(root,build(a[i].rak));
}
for(int i=1;i<=n;i++)
{
int ans=rank(root);
printf("%d",i-1+ans);
if(i!=n)
{
printf(" ");
}
split(root,ans-1,x,y);
split(y,1,y,z);
rotate(x);
root=merge(x,z);
}
}

BZOJ1552[Cerc2007]robotic sort&BZOJ3506[Cqoi2014]排序机械臂——非旋转treap的更多相关文章

  1. [bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂

    非常垃圾的一道平衡树,结果被日了一天.很难受嗷嗷嗷 首先不得不说网上的题解让我这个本来就不熟悉平衡树的彩笔很难受——并不好理解. 还好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法. 题 ...

  2. bzoj3506 [Cqoi2014]排序机械臂

    bzoj3506 此题是一道比较简单的spaly题目. 用splay维护序列,将每个点排到对应的位置之后删除,这样比较容易区间翻转. 我的指针写法在洛谷上AC了,但在bzoj上RE. #include ...

  3. [BZOJ3506] [Cqoi2014] 排序机械臂 (splay)

    Description 同OJ1552 Input Output Sample Input Sample Output HINT Source Solution Q:哎不是同一道题吗为什么分两篇博客来 ...

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

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

  5. [BZOJ1552][Cerc2007]robotic sort

    [BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...

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

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

  7. Luogu P3165 [CQOI2014]排序机械臂

    先讲一下和这题一起四倍经验的题: Luogu P4402 [Cerc2007]robotic sort 机械排序 SP2059 CERC07S - Robotic Sort UVA1402 Robot ...

  8. P3165 [CQOI2014]排序机械臂

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

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

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

随机推荐

  1. docker镜像的创建commit及dockerfile

    在docker 1.3版本以前使用attach进入容器会经常出现卡死的情况,之后官方退出了exec命令,从宿主机进入,但是从其他远程主机进入使用ssh服务来维护是用户熟悉的方法.所以这里来创建一个带有 ...

  2. curl命令行

    curl命令行--强大的工具.通过各种参数,支持各种方式. 写几个常用的命令: 请求到的网站html curl http://www.baidu.com 比如想在命令行上请求一个接口,post过去几个 ...

  3. Django框架知识点整理

    1.安装django, pip install django 或者是通过 “==”符号指定版本号. 2.创建一个Django项目: django-admin createproject project ...

  4. PowerDesign 16.0 生成的SQL Server2000 数据库脚本时MS_Description不存在的问题解决

    根据网上查询到的资料,找到了解决方法,原文出自:http://www.cnblogs.com/24tt/p/5047257.html PowerDesign 16.0 生成的Script语句,Sql2 ...

  5. 【转】单KEY业务,数据库水平切分架构实践

    本文将以“用户中心”为例,介绍“单KEY”类业务,随着数据量的逐步增大,数据库性能显著降低,数据库水平切分相关的架构实践: 如何来实施水平切分 水平切分后常见的问题 典型问题的优化思路及实践 一.用户 ...

  6. bat基础知识

    1.打日志:使用重定向 eg:call test.bat>log/test.log 2.不关闭cmd窗口:使用pause eg: 结果: ps:注意,在自动化运维的时候,比如创建自动发版的脚本的 ...

  7. Codeforces 999D Equalize the Remainders (set使用)

    题目连接:Equalize the Remainders 题意:n个数字,对m取余有m种情况,使得每种情况的个数都为n/m个(保证n%m=0),最少需要操作多少次? 每次操作可以把某个数字+1.输出最 ...

  8. python 文本特征提取 CountVectorizer, TfidfVectorizer

    1. TF-IDF概述 TF-IDF(term frequency–inverse document frequency)是一种用于资讯检索与文本挖掘的常用加权技术.TF-IDF是一种统计方法,用以评 ...

  9. Python 学习 第一篇:数据类型(数字,集合,布尔类型,操作符)

    Python语言最常用的对象是变量和常量,常量的值是字面意思,其值是不可变的,变量的值是可变的,例如,123,"上海"是常量,而a=1,a=2,其中a是变量名.内置的核心数据类型有 ...

  10. Nginx SSL+tomcat集群,request.getScheme() 取到https正确的协议

    最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https协议 但是,明明是https url请求,发现 log里 ...