Splay

与之前不同的是如果你仅仅是翻转左右区间的话可以在find里面做因为对他有影响的子树在做之前一定在他的上面从上到下搜索的过程可以把rever做了。

但这道题要求我们输出转换之前的,因此不能保证之前的rev标记都已执行完因此就要从上到下做一遍。

By:大奕哥

 #include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
int fa[N],c[N][],pos[N],rev[N],mn[N],w[N],size[N],n,m,rt;
struct node
{
int pos,v;
bool operator<(const node &b)const {
if(v==b.v)return pos<b.pos;
return v<b.v;
}
}a[N];
void pushdown(int x)
{
if(rev[x])rev[c[x][]]^=,rev[c[x][]]^=,rev[x]^=,swap(c[x][],c[x][]);
mn[x]=w[x];pos[x]=x;
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
size[x]=size[c[x][]]+size[c[x][]]+;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=(c[y][]==x);int r=l^;
if(y==k)k=x;else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
pushdown(y);pushdown(x);
}
int s[N],top;
void splay(int x,int &k)
{
top=;
for(int i=x;i;i=fa[i])s[++top]=i;
for(int i=top;i;--i)pushdown(s[i]);
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(x==c[y][]^y==c[z][])rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int k)
{
if(!x)return ;pushdown(x);
if(size[c[x][]]+==k)return x;
else if(size[c[x][]]+>k)return find(c[x][],k);
else return find(c[x][],k-size[c[x][]]-);
}
int query(int l,int r)
{
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
return pos[c[y][]];
}
void rever(int l,int r)
{
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
int z=c[y][];
rev[z]^=;
return;
}
void build(int l,int r,int f){
if(l>r)return;
int mid=l+r>>;
fa[mid]=f;c[f][mid>=f]=mid;
w[mid]=mn[mid]=a[mid].v;
if(l==r)
{
rev[mid]=;size[mid]=;pushdown(mid);return;
}
build(l,mid-,mid);build(mid+,r,mid);
pushdown(mid);
return;
}
bool cmp(node aa,node bb){
return aa.pos<bb.pos;
}
int ans[N];
int main()
{
scanf("%d",&n);
build(,n+,);rt=(n+)>>;mn[]=a[].v=a[n+].v=1e9;
for(int i=;i<=n+;++i)scanf("%d",&a[i].v);
for(int i=;i<=n;++i)a[i+].pos=i;
sort(a+,a+n+);
for(int i=;i<=n;++i)a[i+].v=i;
sort(a+,a+n+,cmp);
build(,n+,);
rt=(n+)>>;
for(int i=;i<=n;++i)
{
int x=query(i,n);
splay(x,rt);
ans[i]=size[c[x][]];
rever(i,ans[i]);
}
for(int i=;i<n;++i)
{
printf("%d ",ans[i]);
}
printf("%d",ans[n]);
return ;
}

这个是标准的按照序列中的位置建树,每次splay之前要query一下。跑了3000ms,后来又在网上找了一种写法,直接按照权值建图,查找就直接splay对应的标号即可,2000ms。

 #include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
int fa[N],c[N][],pos[N],rev[N],mn[N],w[N],size[N],n,m,rt;
struct node
{
int pos,v;
bool operator<(const node &b)const {
if(v==b.v)return pos<b.pos;
return v<b.v;
}
}a[N];
bool cmp(node aa,node bb){
return aa.pos<bb.pos;
}
void pushdown(int x)
{
if(rev[x])rev[c[x][]]^=,rev[c[x][]]^=,rev[x]^=,swap(c[x][],c[x][]);
mn[x]=w[x];pos[x]=x;
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
if(mn[c[x][]]<mn[x])mn[x]=mn[c[x][]],pos[x]=pos[c[x][]];
size[x]=size[c[x][]]+size[c[x][]]+;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=(c[y][]==x);int r=l^;
if(y==k)k=x;else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
pushdown(y);pushdown(x);
}
int s[N],top;
void splay(int x,int &k)
{
top=;
for(int i=x;i;i=fa[i])s[++top]=i;
for(int i=top;i;--i)pushdown(s[i]);
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(x==c[y][]^y==c[z][])rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int k)
{
if(!x)return ;pushdown(x);
if(size[c[x][]]+==k)return x;
else if(size[c[x][]]+>k)return find(c[x][],k);
else return find(c[x][],k-size[c[x][]]-);
}
void rever(int l,int r)
{
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
int z=c[y][];
rev[z]^=;
return;
}
void build(int l,int r,int f){
if(l>r)return;
int mid=l+r>>;
int now=a[mid].v,last=a[f].v;
fa[now]=last;c[last][mid>=f]=now;
if(l==r)
{
rev[now]=;size[now]=;return;
}
build(l,mid-,mid);build(mid+,r,mid);
pushdown(now);
return;
}
int ans[N];
int main()
{
scanf("%d",&n);
rt=(n+)>>;mn[]=1e9;
for(int i=;i<=n+;++i)scanf("%d",&a[i].v);
for(int i=;i<=n;++i)a[i+].pos=i;
sort(a+,a+n+);
for(int i=;i<=n+;++i)a[i].v=i;a[].v=;a[n+].v=n+;
sort(a+,a+n+,cmp);
build(,n+,);
rt=a[(n+)>>].v;
for(int i=;i<=n;++i)
{
splay(i+,rt);
ans[i]=size[c[rt][]];
rever(i,ans[i]);
}
for(int i=;i<n;++i)
{
printf("%d ",ans[i]);
}
printf("%d",ans[n]);
return ;
}

BZOJ1552/3506 [Cerc2007]robotic sort的更多相关文章

  1. 洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序

    FHQ_Treap 太神辣 蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目 因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每 ...

  2. 【BZOJ1552】[Cerc2007]robotic sort Splay

    [BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...

  3. 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 806  Solved: 329[Submit][ ...

  4. 【bzoj1552】[Cerc2007]robotic sort

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

  5. 【BZOJ】1552/3506 [Cerc2007]robotic sort

    [算法]splay [题解] splay维护序列,用权值(离散化)作为编号.每次找第i小的话直接找对应编号splay即可. 但是这样splay没有下传翻转标记?直接暴力找到路径然后从根到改结点push ...

  6. 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值

    [bzoj1552/3506][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. ...

  7. [BZOJ1552][Cerc2007]robotic sort

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

  8. BZOJ 1552: [Cerc2007]robotic sort( splay )

    kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...

  9. bzoj 1552: [Cerc2007]robotic sort

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1198  Solved: 457[Submit] ...

随机推荐

  1. Eng1—English daily notes

    English daily notes 2015年 4月 Phrases 1. As a side note #作为附注,顺便说句题外话,和by the way意思相近,例句: @1:As a sid ...

  2. 【洛谷 P2764】 最小路径覆盖问题(最大流)

    题目链接 首先有\(n\)条路径,每条路径就是一个点,然后尽量合并,答案就是点数-合并数. 套路拆点,源连入,出连汇,原有的边入出连. 最大流就是最大合并数,第一问解决. 然后怎么输出方案? 我是找到 ...

  3. echarts初探:了解模块化

    什么是echarts?这是官网:http://echarts.baidu.com/ 简单的说就是百度提供的一些画图表的库,用它你可以简便的画出一些你想要的图表效果. 虽然蛮好用的,但对于不知道模块化的 ...

  4. linux学习记录.2.hello world.c

    安装vim,指令: sudo apt-get install vim 建立一个子目录WorkSpace,指令 mkdir WorkSpace 转到该目录下,指令 cd WorkSpace 新建c文件, ...

  5. Mysql储存过程6: in / out / inout

    in 为向函数传送进去的值 out 为函数向外返回的值 intout 传送进去的值, 并且还返回这个值 )) begin then select 'true'; else select 'false' ...

  6. 目标检测-基于Pytorch实现Yolov3(1)- 搭建模型

    原文地址:https://www.cnblogs.com/jacklu/p/9853599.html 本人前段时间在T厂做了目标检测的项目,对一些目标检测框架也有了一定理解.其中Yolov3速度非常快 ...

  7. LSTM及其变种及其克服梯度消失

    本宝宝又转了一篇博文,但是真的很好懂啊: 写在前面:知乎上关于lstm能够解决梯度消失的问题的原因: 上面说到,LSTM 是为了解决 RNN 的 Gradient Vanish 的问题所提出的.关于 ...

  8. Java容器概述

    如果一个程序只包含固定数量的且其生命期都是己知的对象. 那么这是一个非常简单的程序. 通常,程序总是根据运行时才知道的某些条件去创建新对象.在此之前,不会知道所需对象的数量,甚至不知道确切的类型.为解 ...

  9. 基于layui+cropper.js实现上传图片的裁剪功能

    最近因项目需求,需要在上传图片的时候先对图片裁剪,然后在上传,所以就有了本文的出现. 开始正文之前,要提一下这个图片的裁剪:图片的裁剪,有前端裁剪,也可以后端裁剪 前端的裁剪我知道的可以分为这么两种: ...

  10. Linux下文件特殊权限

    SUIDSUID表示在所有者的位置上出现了s在一个命令的所有者的权限上如果出现了s,当其他人在执行该命令的时候将具有所有者的权限.SUID权限仅对二进制文件有效 SGID表示在组的位置上出现了s如果一 ...