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. Centos tomcat jmx 远程连接

    jmx配置: -Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.mana ...

  2. phpcms模板

    cms的样式有很多种,我们学习的是phpcms,这些cms都是大同小异,学会了一种就可以使用其它的cms. PHPCMS是一款网站管理软件.该软件采用模块化开发,支持多种分类方式,使用它可方便实现个性 ...

  3. 如何实用便捷的在本地真机调试WEB端HTML5网页

    先简单介绍两款常用但需要一定条件或限制的工具 1.如果你能FQ chrome在32版本后就自带了移动端调度工具,可以在Android直接联调,但唯一遗憾的是,在我大天朝要FQ后才能行的通,我自己试了后 ...

  4. Double类型的数向上取整和向下取整

  5. Linux 下解决安装多个node冲突的问题(重新安装node)

    一个系统中不经意安装了多个node版本,结果更新后还是原来的版本,下面思考一下解决办法: 敲黑板: 1. nodejs 用 包管理器安装一般在 /usr/local/bin 2. 查看当前目录下的no ...

  6. 阿里Java研发工程师实习面经,附面试技巧

    作者:如何进阿里 链接:https://www.nowcoder.com/discuss/72899?type=0&order=0&pos=17&page=1 来源:牛客网 前 ...

  7. 关于HTML5服务器发送事件(SSE)

    最近在看 W3School 上关于 HTML 5 的教程.在看到 HTML 5 服务器发送事件 ( SSE, server-sent event ) 时,没怎么弄明白示例代码是怎么回事,寻找其他教程, ...

  8. chm转换为html文件

    在Windows下chm转换为html的超简单方法(反编译CHM文件的方法) 通过调用Windows命令,将chm 文件转换为html 文件. 方法: 命令行(cmd),输入hh -decompile ...

  9. 转:google测试分享-GTA

    原文: http://blog.sina.com.cn/s/blog_6cf812be0102viuh.html 上一次分享了google测试分享-分层测试,有很多自动化测试的策略和实施都要有一个重点 ...

  10. 使用亚马逊云服务器EC2做深度学习(四)配置好的系统镜像

    这是<使用亚马逊云服务器EC2做深度学习>系列的第四篇文章. (一)申请竞价实例  (二)配置Jupyter Notebook服务器  (三)配置TensorFlow  (四)配置好的系统 ...