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. cropper.js 跨域问题

    this.$clone = $clone = $('<img>'); $clone.one('load', $.proxy(function () { var naturalWidth = ...

  2. CAD启动提示"是否关闭命令行"不管点击什么,都会闪退的解决办法

    AutoCAD splash screen starts up and then closes   AutoCAD splash screen starts up and then closes (S ...

  3. 多维尺度变换MDS(Multidimensional Scaling)

    流形学习(Manifold Learning)是机器学习中一大类算法的统称,流形学习是非线性的降维方法(an approach to non-linear dimensionality reducti ...

  4. jsoup抓取网页报错UnsupportedMimeTypeException

    今天在用Jsoup爬虫的时候两次遇到下面错误 Exception in thread "main" org.jsoup.UnsupportedMimeTypeException: ...

  5. MAC和PHY的区别 (转自http://www.cnblogs.com/feitian629/archive/2013/01/25/2876857.html)

    一块以太网网卡包括OSI(开方系统互联)模型的两个层.物理层和数据链路层.物理层定义了数据传送与接收所需要的电与光信号.线路状态.时钟基准.数据编码和电路等,并向数据链路层设备提供标准接口.数据链路层 ...

  6. Linux系统中提示/usr/bin/ld: cannot find -lxxx错误的通用解决方法

    在linux环境编译应用程式或lib的source code时常常会出现如下的错误讯息: 代码如下: /usr/bin/ld: cannot find -lxxx 这些讯息会随着编译不同类型的sour ...

  7. .NET连接Oracle的方法

    .NET连接Oracle的方法 方式1:直接利用.NET的oracle驱动连接 引用System.data.oracleclient; using System.data.oracleclient; ...

  8. C/C++——C语言跳出多重循环方法

    c语言的break语句只能跳出离它最近的一层循环,但是我们有时候需要跳出多层循环,以下有几种跳出多重循环的方法: 1. 使用goto ; i < MAX1; i++) { ; j < MA ...

  9. PHP的instanceof关键字

    PHP5的另一个新成员是instdnceof关键字.使用这个关键字可以确定一个对象是类的实例.类的子类,还是实现了某个特定接口,并进行相应的操作.在某些情况下,我们希望确定某个类是否特定的类型,或者是 ...

  10. 转 proc文件

    /proc 是一个伪文件系统, 被用作内核数据结构的接口, 而不仅仅是解释说明/dev/kmem. /proc 里的大多数文件都是只读的, 但也可以通过写一些文件来改变内核变量. 下面对整个 /pro ...